Both child and parent are clickable (child could be a link or div with jQuery click events). When I click on child, how do I only trigger parent click event but not the child event?
DOM Event Phases
Events have three phases:
Capture: The first phase is "capture" where event handlers are called starting with the <window> and moving down through descendants towards the target of the event.
Target: The second phase is the "target" phase when the event listeners on the target are called.
Bubbling: The third phase is "bubbling" which starts with the handlers listening on parent of the target being called first, then, progressively, the ancestors of that element.
Events also have a "default action", which happens after the bubbling phase. The default action is the browser-defined action that normally occurs for events of the specified type on the kind of element which is the target of the event (e.g. the browser navigating to the href of an <a> upon a click, whereas a click on another type of element will have a different default action).
The DOM Level 3 Events draft has a diagram that graphically shows how events propagate through the DOM:
Image Copyright © 2016 World Wide Web Consortium, (MIT, ERCIM, Keio, Beihang). http://www.w3.org/Consortium/Legal/2015/doc-license (Use permitted per the license)
For more information, on capture and bubbling, see: "What is event bubbling and capturing?"; The DOM Level 3 Events draft; or W3C DOM4: Events
Preventing the event from getting to the child
For what you want, to get the event on the parent prior to, and prevent, the event on the child, you have to receive the event in the capture phase. Once you have received it in the capture phase, you have to stop the event from propagating to any event handlers on elements lower in the DOM tree, or which have registered to listen in the bubbling phase (i.e. all listeners on elements/phases which would be visited by the event after your listener). You do this by calling event.stopPropagation().
Receiving events during the capture phase
When adding the listener with addEventListener(type, listener[, useCapture]), you can have the useCapture argument be true.
Quoting MDN:
[useCapture is] A Boolean that indicates that events of this type will be dispatched to the registered listener before being dispatched to any EventTarget beneath it in the DOM tree. Events that are bubbling upward through the tree will not trigger a listener designated to use capture. Event bubbling and capturing are two ways of propagating events that occur in an element that is nested within another element, when both elements have registered a handle for that event. The event propagation mode determines the order in which elements receive the event. See DOM Level 3 Events and JavaScript Event order for a detailed explanation. If not specified, useCapture defaults to false.
Preventing other handlers getting the event
event.preventDefault() is used to prevent the default action (e.g. prevent the browser from navigating to the href of an <a> upon a click). [This is used in the example below, but has no real effect as there is no default action for text. It's used here because most of the time when you are adding a click event handler you want to prevent the default action. Thus, it's a good idea to be in the habit of doing so, and just not doing so when you know you don't want to.]
event.stopPropagation() is used to prevent any handlers on elements later in any of the event phases from receiving the event. It does not prevent any additional handlers on the current element and phase from being called. It does not prevent the default action from occurring.
event.stopImmediatePropagation(): Handlers on the same element and phase are called in the order in which they are added. In addition to having the same effect as event.stopPropagation(), event.stopImmediatePropagation() prevents any additional handlers on the same element and event phase from receiving the event. It does not prevent the default action from occurring. Given that the requirement for this question is to prevent the event from propagating to children, we don't need to use this, but could do so instead of using event.stopPropagation(). Note, however, that listeners on the same element are called in the order they are added. Thus, event.stopImmediatePropagation() will not prevent the event from being received by those listeners on the same element and phase as your listener which were added prior to your listener.
Example
In the following example, event listeners are placed on both the parent and the child <div> elements. Only the listener placed on the parent receives the event because it receives the event during the capture phase prior to the child and it executes event.stopPropagation().
var parent=document.getElementById('parent');
var child=document.getElementById('child');
var preventChild=document.getElementById('preventChild');
parent.addEventListener('click',function(event){
if(preventChild.checked) {
event.stopPropagation();
}
event.preventDefault();
var targetText;
if(event.target === parent) {
targetText='parent';
}
if(event.target === child) {
targetText='child';
}
console.log('Click Detected in parent on ' + targetText);
},true);
child.addEventListener('click',function(event){
console.log('Click Detected in child (bubbling phase)');
});
child.addEventListener('click',function(event){
console.log('Click Detected in child (capture phase)');
},true);
<input id="preventChild" type="checkbox" checked>Prevent child from getting event</input>
<div id="parent">Parent Text<br/>
<div id="child" style="margin-left:10px;">Child Text<br/>
</div>
</div>
jQuery
jQuery does not support using capture on events. For more information as to why see: "Why does jQuery event model does not support event Capture and just supports event bubbling"
Another option for this that may be useful in certain circumstances when you know that none of the child elements are interactive is to set pointer-events: none in your css (link). I usually apply it to all child elements of the element on which I want to capture interaction. Like this:
#parentDiv * {
pointer-events: none
}
Note the *, declaring that the rule applies to all children of the parentDiv.
Prevent the children from receiving the parent's click event:
parent.addEventListener('click',function(e){
e.stopPropagation();
console.log('event on parent!')
},true);
(Note that the second parameter is true)
Prevent the parent from receiving itself or it children's click event:
parent.addEventListener('click',function(e){
e.stopPropagation();
console.log('event on parent or childs!', e.target.closest('.parent_selector'))
});
e.stopPropagation means that stop next ones in the hierarchy to receive the event.
second argument (useCapture) is a flag, and means that reverse the order of receiving events. (use capture phase instead of bubble phase.).
it means if you set it to true, parent will receive the click event, then the child. (normally the child will get the event first.)
(see the #Makyen's answer for detailed explanation.)
To make life really simple and easy here i am
Use on parent node similar to this
target_image.addEventListener('drop',dropimage,true);
This will enable the parent child ancestor relationship and the same event will be called in for the parent and child.
To make the event only be called for the parent use the following code snippet in the event handler. First line
event.stopPropagation();
event.preventDefault();
You can use $event.stopPropagation() in the html file.
(click)="openAttendeesList(event.id,event.eventDetailId,event.eventDate) ; $event.stopPropagation();"
You can use the CustomEvents property on elements.
Create an event object and let the child element dispatch the event to its parent
see demo here
document.getElementById('parent').onclick = function() {
alert("you are clicking on the parent stop it");
}
document.getElementById('child').onclick = function(e) {
alert('I am sending this event to my parent');
event = new CustomEvent('click');
document.getElementById('parent').dispatchEvent(event);
}
#parent {
display: inline-block;
width: 100px;
height: 100px;
border: solid black;
}
#child {
border: solid red;
}
<div id=parent>
<div id=child>I am a child</div>
</div>
Related
So I have a button that is inside an <a> tag that links to another location. When I click the button I want it so that it does not trigger the link in the parent tag. I have tried using $event.stopPropagation() but it does not seem to work.
here is my html:
<div class="column" ng-repeat="eventObj in events" ng-repeat-dimmer>
<a href="#/sample-event/{{eventObj.eventId}}">
//divs
<h2>{{eventObj.eventName}}</h2>
<div>{{eventObj.eventStart | date}} - {{eventObj.eventEnd | date}}</div>
<h5>{{eventObj.eventVenue}}</h5>
<button ng-click="deleteEvent(eventObj,$event)"></button>
//divs
<img class="ui image" src="assets/img/sampleevent.png"/>
</a>
</div>
and the function in my controller:
$scope.deleteEvent = function(delEvent,$event){
$event.stopPropagation();
console.log($event.isPropagationStopped())
$scope.targetEvent = delEvent;
if(confirm("Note: This will permanently delete the event and games associated with it.")==true){
EventService.deleteEvent($scope.targetEvent)
.then(function(){
EventService.getEvents()
.then(function(events){
$scope.events = events;
});
})
window.location.reload();
}
}
What do I do here?
Use event.preventDefault instead, here is an example
<script>
function clickFunction(e)
{
alert('click');
e.preventDefault();
}
</script>
<a href="http://google.com" target="_blank">
<button onclick="clickFunction(event);">
test
</button>
</a>
https://jsfiddle.net/3Lrr24qu/
As to why it doesn't work, triggering hyperlink is a default event not an event listener. If you had an onclick instead of the href on the link the event.stopPropagation would work, see the documentation below.
From https://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-flow-capture :
1.2.3. Event bubbling
Events which are designated as bubbling will initially proceed with the same event flow as non-bubbling events. The event is dispatched to its target EventTarget and any event listeners found there are triggered. Bubbling events will then trigger any additional event listeners found by following the EventTarget's parent chain upward, checking for any event listeners registered on each successive EventTarget. This upward propagation will continue up to and including the Document. EventListeners registered as capturers will not be triggered during this phase. The chain of EventTargets from the event target to the top of the tree is determined before the initial dispatch of the event. If modifications occur to the tree during event processing, event flow will proceed based on the initial state of the tree.
Any event handler may choose to prevent further event propagation by calling the stopPropagation method of the Event interface. If any EventListener calls this method, all additional EventListeners on the current EventTarget will be triggered but bubbling will cease at that level. Only one call to stopPropagation is required to prevent further bubbling.
1.2.4. Event cancelation
Some events are specified as cancelable. For these events, the DOM implementation generally has a default action associated with the event. An example of this is a hyperlink in a web browser. When the user clicks on the hyperlink the default action is generally to active that hyperlink. Before processing these events, the implementation must check for event listeners registered to receive the event and dispatch the event to those listeners. These listeners then have the option of canceling the implementation's default action or allowing the default action to proceed. In the case of the hyperlink in the browser, canceling the action would have the result of not activating the hyperlink.
Cancelation is accomplished by calling the Event's preventDefault method. If one or more EventListeners call preventDefault during any phase of event flow the default action will be canceled.
Different implementations will specify their own default actions, if any, associated with each event. The DOM does not attempt to specify these actions.
I want to do something on all clicks except on a certain element.
I've created a very simple example which demonstrates the issue: http://jsfiddle.net/nhe6wk77/.
My code:
$('body').on('click', ':not(a)', function () {
// do stuff
});
I'd expect all click to on <a> to be ignored, but this is not the case.
Am I doing something wrong or is this a bug on jQuery's side?
There's a lot going on in that code that's not obvious. Most importantly, the click event is actually attached to the body element. Since that element isn't an anchor, you'll always get the alert. (Event delegation works because the click event bubbles up from the a through all its ancestors, including body, until it reaches document.)
What you want to do is check the event.target. That will tell you the element that was actually clicked on, but the actual click event is still bound to the body element:
$('body').on('click', function (e) { // e = event object
if ($(e.target).is(':not(a)')) {
alert('got a click');
}
});
http://jsfiddle.net/y3kx19z7/
No this is not a bug but rather intended behaviour.
The event bubbles all the way up. By clicking the a node, you are still triggering it's parents event from the div node.
Read more about event bubbling in the W3C DOM Specification. Just search for "bubble".
You need to stop the event propagation of the a nodes. i.e.:
$('body').on('click', ':not(a)', function () {
// do something effectively
alert('you should not see me when clicking a link');
});
$("a").click(function( event ) {
// do nothing effectively, but stop event bubbling
event.stopPropagation();
});
JSFiddle: http://jsfiddle.net/nhe6wk77/6/
It's working as intended, here's why!
Use of the :not() selector is honored in delegated events, but it's an uncommon practice because of how events bubble up the DOM tree potentially triggering the handler multiple times along the way.
The jQuery API Documentation states that:
jQuery bubbles the event from the event target up to the element where the handler is attached (i.e., innermost to outermost element) and runs the handler for any elements along that path matching the selector.
Notice the phrase "and runs the handler for any elements along that path matching the selector".
In your example, jQuery is accurately not running the handler on the a element, but as the event bubbles up the tree, it runs the handler for any element that matches :not(a), which is every other element in the path.
Here is a clear example showing how this works: http://jsfiddle.net/gfullam/5mug7p2m/
$('body').on('click', ':not(a)', function (e) {
alert($(this).text());
});
<div class="outer">
<div class="inner">
Click once, trigger twice
</div>
</div>
<div class="outer">
<div class="inner">
<button type="button">Click once, trigger thrice</button>
</div>
</div>
Clicking on the link in the first block of nested divs, will start the event bubbling, but the clicked a element — a.k.a. the event target — doesn't trigger the handler because it doesn't match the :not(a) selector.
But as the event bubbles up through the DOM, each of its parents — a.k.a the event currentTarget — triggers the handler because they do match the :not(a) selector, causing the handler to run twice. Multiple triggering is something to be aware of since it may not be a desired result.
Likewise, clicking on the button in the second block of nested divs, will start the event bubbling, but this time the event target does match the :not(a) selector, so it triggers the handler immediately. Then as the event bubbles up, each of its parents matching the selector triggers the handler, too, causing the handler to run three times.
As others have suggested, you need to either bind an alternate handler that stops propagation on a click events or check the event target against the :not(a) selector inside your handler instead of the delegated selector.
$("body").click(function(e) {
if($(e.target).is('a')){
e.preventDefault();
return;
}
alert("woohoo!");
});
check the target of the click. this way you dont need to bind another event.
updated fiddle
For example we have a page with a link that has onclick event listener on it. But handler makes stopPropagation. How I can handle that click event was made, if it's not bubble to root anymore?
e.g.
document.addEventListener('click', function(e) {console.log(e);});
a.onclick = function(e) {e.stopPropagation();};
DOM event propagation works in three phases: the capture phase, the target phase and the bubble phase. Roughly, the event first works its way down to the target, reaches the target and then works its way back up.
By default, event handlers are attached in the final bubble phase. If you attach a click event listener in the first capture phase, it will run before the previous handler has had the chance to call stopPropagation.
See this question for a deeper explanation.
The simple answer is, add a third argument, true, when adding your event listener.
document.addEventListener('click', someFunction, true)
This flag (called useCapture) will call someFunction on all clicks in a document, even when the user clicked inside an element with a click handler that called event.stopPropagation.
With options
If you're already passing an object of options as the third argument, simply include capture: true in them:
document.addEventListener('click', someFunction, { capture: true, ...someMoreOptions })
Why?
Enabling the handler's useCapture mode like this means the listener listens during the earlier "capture" phase of the event (which starts at the outmost element then trickles down through children), instead of the later "bubble" phase (which starts at the innermost element and bubbles back up through ancestors, and is the one stopPropagation blocks).
Side effects
That also means that applying this setting changes the timing: your capture phase click event will occur before any click events of either type inside child or descendant elements.
For example, in the above function, if a user clicks on a button on the page, the someFunction attached to the document's capture phase will be called before any handlers attached to the button; whereas without setting use capture to true, you'd expect it to be called after.
Could somebody please explain the bubbling and capturing phase with this code according to output of the 4 cases in code , on clicking div2 and div1
http://jsfiddle.net/JuKmM/9/
code:
function doSomething2(){
console.log("div 1 clicked");
}
var element1=document.getElementById('div_1');
var element2=document.getElementById('div_2');
element1.addEventListener('click',doSomething2,false);
element2.addEventListener('click',doSomething,true);
//element1.addEventListener('click',doSomething2,false);
//element2.addEventListener('click',doSomething,false);
//element1.addEventListener('click',doSomething2,true);
//element2.addEventListener('click',doSomething,true);
//element1.addEventListener('click',doSomething2,true);
//element2.addEventListener('click',doSomething,false);
function doSomething(){
console.log("div2 clicked");
}
From the MDN documentation:
useCapture Optional
If true, useCapture indicates that the user wishes to initiate capture. After initiating capture, all events of the specified type will be dispatched to the registered listener before being dispatched to any EventTarget beneath it in the DOM tree. Events which are bubbling upward through the tree will not trigger a listener designated to use capture. See DOM Level 3 Events for a detailed explanation. If not specified, useCapture defaults to false.
You're setting up the handler for "div_1" such that it does not use capture, and the handler for "div_2" such that it does, though since it's got no children that doesn't matter much. Thus:
A click on the blue part ("div_1") triggers only the handler on that element.
A click on the red part ("div_2") triggers the handler for that element. The event then bubbles up the DOM to "div_1", and that handler is triggered.
I have read article at https://developer.mozilla.org/en/DOM/element.addEventListener but unable to understand useCapture attribute. Definition there is:
If true, useCapture indicates that the user wishes to initiate capture. After initiating capture, all events of the specified type will be dispatched to the registered listener before being dispatched to any EventTargets beneath it in the DOM tree. Events which are bubbling upward through the tree will not trigger a listener designated to use capture.
In this code parent event triggers before child,so I am not able to understand its
behavior.Document object has usecapture true and child div has usecapture set false and document usecapture is followed.So why document property is preferred over child.
function load() {
document.addEventListener("click", function() {
alert("parent event");
}, true);
document.getElementById("div1").addEventListener("click", function() {
alert("child event");
}, false);
}
<body onload="load()">
<div id="div1">click me</div>
</body>
Events can be activated at two occasions: At the beginning ("capture"), and at the end ("bubble").
Events are executed in the order of how they're defined. Say, you define 4 event listeners:
window.addEventListener("click", function(){console.log(1)}, false);
window.addEventListener("click", function(){console.log(2)}, true);
window.addEventListener("click", function(){console.log(3)}, false);
window.addEventListener("click", function(){console.log(4)}, true);
The log messages will appear in this order:
2 (defined first, using capture=true)
4 (defined second using capture=true)
1 (first defined event with capture=false)
3 (second defined event with capture=false)
I find this diagram is very useful for understanding the capture/target/bubble phases:
http://www.w3.org/TR/2003/NOTE-DOM-Level-3-Events-20031107/events.html#Events-phases
Below, content extracted from the link.
Phases
The event is dispatched following a path from the root of the tree to this target node. It can then be handled locally at the target node level or from any target's ancestors higher in the tree. The event dispatching (also called event propagation) occurs in three phases and the following order:
The capture phase: the event is dispatched to the target's ancestors
from the root of the tree to the direct parent of the target node.
The target phase: the event is dispatched to the target node.
The bubbling phase: the event is dispatched to the target's
ancestors from the direct parent of the target node to the root of
the tree.
The target's ancestors are determined before the initial dispatch of the event. If the target node is removed during the dispatching, or a target's ancestor is added or removed, the event propagation will always be based on the target node and the target's ancestors determined before the dispatch.
Some events may not necessarily accomplish the three phases of the DOM event flow, e.g. the event could only be defined for one or two phases. As an example, events defined in this specification will always accomplish the capture and target phases but some will not accomplish the bubbling phase ("bubbling events" versus "non-bubbling events", see also the Event.bubbles attribute).
Capture Event (useCapture = true) vs Bubble Event (useCapture = false)
MDN Reference
Capture Event will be dispatch before Bubble Event
Event propagation order is
Parent Capture
Children Capture
Target Capture and Target Bubble
In the order they were registered
When the element is the target of the event, useCapture parameter doesn't matter (Thanks #bam and #legend80s)
Children Bubble
Parent Bubble
stopPropagation() will stop the flow
Demo
Result:
Parent Capture
Target Bubble 1
(Because Capture and Bubble of Target will trigger in the order they were registered, so this is trigger first)
Target Capture
Target Bubble 2
Parent Bubble
var parent = document.getElementById('parent');
var target = document.getElementById('target');
// "target" will trigger in the order of register (addEventListener()), capture / bubble don't affect the order
// #2
target.addEventListener('click', function (e) {
console.log('Target Bubble 1');
// e.stopPropagation();
}, false);
// #3
target.addEventListener('click', function (e) {
console.log('Target Capture');
// e.stopPropagation();
}, true);
// #4
target.addEventListener('click', function (e) {
console.log('Target Bubble 2');
// e.stopPropagation();
}, false);
// #1 : "parent capture" first
parent.addEventListener('click', function (e) {
console.log('Parent Capture');
// e.stopPropagation();
}, true);
// #5 : "parent bubble" last
parent.addEventListener('click', function (e) {
console.log('Parent Bubble');
// e.stopPropagation();
}, false);
<div id="parent">
<button id="target" style="padding: 1em 0.8em;">
Trigger event
</button>
</div>
When you say useCapture = true the Events execute top to down in the capture phase when false it does a bubble bottom to top.
Summary:
The DOM spec described in:
https://www.w3.org/TR/2003/NOTE-DOM-Level-3-Events-20031107/events.html#Events-phases
works the following manner:
An event is dispatched following a path from the root (document) of the tree to the target node. The target node is the most deep HTML element, i.e. the event.target. The event dispatching (also called event propagation) occurs in three phases and the following order:
The capture phase: the event is dispatched to the target's ancestors from the root of the tree (document) to the direct parent of the target node.
The target phase: the event is dispatched to the target node. Target phase is always on the deepest html element on which the event was dispachted.
The bubbling phase: the event is dispatched to the target's ancestors from the direct parent of the target node to the root of the tree.
Example:
// bubbling handlers, third argument (useCapture) false (default)
document.getElementById('outerBubble').addEventListener('click', () => {
console.log('outerBubble');
}, false)
document.getElementById('innerBubble').addEventListener('click', () => {
console.log('innerBubble');
}, false)
// capturing handlers, third argument (useCapture) true
document.getElementById('outerCapture').addEventListener('click', () => {
console.log('outerCapture');
}, true)
document.getElementById('innerCapture').addEventListener('click', () => {
console.log('innerCapture');
}, true)
div:hover{
color: red;
cursor: pointer;
}
<!-- event bubbling -->
<div id="outerBubble">
<div id="innerBubble">click me to see Bubbling</div>
</div>
<!-- event capturing -->
<div id="outerCapture">
<div id="innerCapture">click me to see Capturing</div>
</div>
The above example really illustrates the difference between event bubbling and event capturing. When adding the event listeners with addEventListener, there is a third element called useCapture. This a boolean which when set to true allows the event listener to use event capturing instead of event bubbling.
In our example when we set the useCapture argument to false we see that event bubbling takes place. First the event at the target phase is fired (logs innerBubble), and then via event bubbling the event in the parent element is fired (logs outerBubble).
When we set the useCapture argument to true we see that the event in the outer <div> is fired first. This is because the event is now fired in the capturing phase and not the bubbling phase.
It's all about event models: http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-flow
You can catch event in bubbling phase or in capturing phase. Your choice.
Take a look at http://www.quirksmode.org/js/events_order.html - you'll find it very useful.
Code example:
<div id="div1" style="background:#9595FF">
Outer Div<br />
<div id="div2" style="background:#FFFFFF">
Inner Div
</div>
</div>
Javascript code:
d1 = document.getElementById("div1");
d2 = document.getElementById("div2");
if both are set to false
d1.addEventListener('click',function(){alert("Div 1")},false);
d2.addEventListener('click',function(){alert("Div 2")},false);
Executes: Onclicking Inner Div, alerts are displayed as:
Div 2 > Div 1
Here the script is executed from the inner element: Event Bubbling (useCapture has been set to false)
div 1 is set to true and div 2 set to false
d1.addEventListener('click',function(){alert("Div 1")},true);
d2.addEventListener('click',function(){alert("Div 2")},false);
Executes: Onclicking Inner Div, alerts are displayed as:
Div 1 > Div 2
Here the script is executed from the ancestor / outer element: Event Capturing (useCapture has been set to true)
div 1 is set to false and div 2 set to true
d1.addEventListener('click',function(){alert("Div 1")},false);
d2.addEventListener('click',function(){alert("Div 2")},true);
Executes: Onclicking Inner Div, alerts are displayed as:
Div 2 > Div 1
Here the script is executed from the inner element: Event Bubbling (useCapture has been set to false)
div 1 is set to true and div 2 set to true
d1.addEventListener('click',function(){alert("Div 1")},true);
d2.addEventListener('click',function(){alert("Div 2")},true);
Executes: Onclicking Inner Div, alerts are displayed as:
Div 1 > Div 2
Here the script is executed from the ancestor / outer element: Event Capturing since useCapture has been set to true
Given the three phases of event travel:
The capture phase: the event is dispatched to the target's ancestors from the root of the tree to the direct parent of the target
node.
The target phase: the event is dispatched to the target node.
The bubbling phase: the event is dispatched to the target's ancestors from the direct parent of the target node to the root of the
tree.
useCapture indicates for which phases the event travel will be on:
If true, useCapture indicates that the user wishes to add the event
listener for the capture phase only, i.e. this event listener will not
be triggered during the target and bubbling phases. If false, the
event listener will only be triggered during the target and bubbling
phases
Source is the same as the second best answer: https://www.w3.org/TR/2003/NOTE-DOM-Level-3-Events-20031107/events.html#Events-phases
The order of definition only matters if the items are at the same level. If you reverse the order of definition in your code you will get the same results.
However, if you reverse the useCapture setting on the two event handlers, the child event handler responds before that of the parent. The reason for this is that the child event handler will now be triggered in the capture phase which is prior to the bubbling phase in which the parent event handler will be triggered.
If you set useCapture to true for both event handlers--regardless of order of definition--the parent event handler will be triggered first because it comes before the child in the capturing phase.
Conversely, if you set useCapture to false for both event handlers--again regardless of order of definition--the child event handler will be triggered first because it comes before the parent in the bubbling phase.