JSFiddle - React, Tailwind, and code Playground
by Vincent Maglione
HTML
<p>
<strong>Event phase for clicked boxes</strong><br>
<label for="clickRad1">Bubble (default)</label>
<input type="radio" name="boxPhase" value="false" id="clickRad1" checked />
<label for="clickRad2">Capture</label>
<input type="radio" name="boxPhase" value="true" id="clickRad2" />
</p>
<p>
<strong>Event phase for <span style="color:papayawhip;">#content</span></strong><br>
<label for="clickRad3">Bubble (default)</label>
<input type="radio" name="contentPhase" value="false" id="clickRad3" checked />
<label for="clickRad4">Capture</label>
<input type="radio" name="contentPhase" value="true" id="clickRad4" />
</p>
<main id="content">
<div id="b1" class="box">
1
<div id="b2" class="box">
2
<div id="b3" class="box">
3
</div>
</div>
</div>
</main>
<footer>
<button id="clearMsg">
Clear
</button>
<p id="clickMsg">
No clicks
</p>
</footer>
SCSS
* {
box-sizing: border-box;
}
#content {
background: papayawhip;
border: 1px solid rgba(255, 0, 0, 0.5);
padding: 1em;
width: 100%;
}
.box {
border: 1px solid rgba(0,0,0,0.2);
padding: 2em;
text-align: center;
width: 100%;
&:hover {
background: rgba(0,0,0,0.1);
}
}
JavaScript
var content = document.getElementById('content'),
boxes = document.getElementsByClassName('box'),
clickMsg = document.getElementById('clickMsg'),
msg = '',
boxPhase = false,
contentPhase = false,
boxCfg = document.querySelectorAll('input[name=boxPhase]'),
contentCfg = document.querySelectorAll('input[name=contentPhase]');
var checkPhase = function(phase) {
if (1 === phase) {
return 'Capturing';
} else if (2 === phase) {
return 'At Target';
} else if (3 === phase) {
return 'Bubbling';
}
return 'No phase';
}
var handleClicks = function(e) {
clickMsg.innerHTML = msg;
var phase = e.eventPhase;
msg += e.target.id.toString() + ' phase: ' + checkPhase(phase) + '<br>';
clickMsg.innerHTML = msg;
}
var handleBubbles = function(e) {
var phase = e.eventPhase;
msg += '<strong>#content</strong> heard event from ' + e.target.id.toString() + ' via ' + checkPhase(phase) + '<br>';
clickMsg.innerHTML = msg;
}
var setupListeners = function(els) {
for (var i = els.length - 1; i > -1; i--) {
var el = els[i];
el.addEventListener('click', handleClicks, boxPhase);
}
content.addEventListener('click', handleBubbles, contentPhase)
}(boxes);
var getChecked = function(els) {
let l = els.length;
if (l) {
for (let i = 0; i < l; i++) {
return els[i].checked ? false : true
}
}
return false
}
var resetListeners = function(els, fn, phase) {
let l = els.length;
if (l) {
for (var i = 0; i < l; i++) {
els[i].removeEventListener('click', fn, !phase);
els[i].addEventListener('click', fn, phase);
}
} else {
els.removeEventListener('click', fn, !phase);
els.addEventListener('click', fn, phase);
}
}
var updateBoxPhase = function(els) {
boxPhase = getChecked(boxCfg);
resetListeners(boxes, handleClicks, boxPhase);
}
var updateContentPhase = function(els) {
contentPhase = getChecked(contentCfg);
resetListeners(content, handleBubbles,...