I want to switch between 2 HTML page layouts (layout1 and layout2), whereat layout2 is derived (cloned) from layout1 since they are almost identical. I have simplified my project to this small example which shows my problem: layout1 does not appear again on the 2nd button click. Can someone please give me a hint why this does happen? Thank you very much in advance:
let active_layout = 1;
document.addEventListener('DOMContentLoaded', function () {
const button = document.getElementById('button');
const layout1 = document.getElementById('layout1');
const layout2 = document.getElementById('layout2');
layout2.classList.add('hidden');
button.addEventListener('click', function () {
if (active_layout === 1) {
let elm_cloned = layout1.cloneNode(true);
elm_cloned.querySelector('h1').textContent = 'Layout 2';
elm_cloned.querySelector('p').textContent = 'This is layout 2.';
layout2.innerHTML = '';
layout2.appendChild(elm_cloned);
layout1.classList.add('hidden');
layout2.classList.remove('hidden');
} else {
layout1.classList.remove('hidden');
layout2.classList.add('hidden');
}
active_layout = (active_layout === 1) ? 2 : 1;
});
});
.layout1,
.layout2 {
background-color: #f0f0f0;
padding: 20px;
margin: 10px;
}
.layout1.hidden,
.layout2.hidden {
display: none;
}
<div class="layout1" id="layout1">
<h1>Layout 1</h1>
<button id="button">Switch Layout</button>
<p>This is layout 1.</p>
</div>
<!-- Layout 2 -->
<div class="layout2" id="layout2">
<!-- Content of Layout 2 will be cloned from Layout 1 during runtime -->
</div>
The problem is that event listeners are not cloned/transferred together with the DOM.
So, if you move button outside of the layout1, it works just fine:
let active_layout = 1;
document.addEventListener('DOMContentLoaded', function () {
const button = document.getElementById('button');
const layout1 = document.getElementById('layout1');
const layout2 = document.getElementById('layout2');
layout2.classList.add('hidden');
button.addEventListener('click', function () {
if (active_layout === 1) {
let elm_cloned = layout1.cloneNode(true);
elm_cloned.querySelector('h1').textContent = 'Layout 2';
elm_cloned.querySelector('p').textContent = 'This is layout 2.';
layout2.innerHTML = '';
layout2.appendChild(elm_cloned);
layout1.classList.add('hidden');
layout2.classList.remove('hidden');
} else {
layout1.classList.remove('hidden');
layout2.classList.add('hidden');
}
active_layout = (active_layout === 1) ? 2 : 1;
});
});
.layout1,
.layout2 {
background-color: #f0f0f0;
padding: 20px;
margin: 10px;
}
.layout1.hidden,
.layout2.hidden {
display: none;
}
<button id="button">Switch Layout</button>
<div class="layout1" id="layout1">
<h1>Layout 1</h1>
<p>This is layout 1.</p>
</div>
<!-- Layout 2 -->
<div class="layout2" id="layout2">
<!-- Content of Layout 2 will be cloned from Layout 1 during runtime -->
</div>
Also, you should move adding/removing DOM elements to outside of event listener, and just manipulate style within the listener:
let active_layout = 1;
document.addEventListener('DOMContentLoaded', function () {
const button = document.getElementById('button');
const layout1 = document.getElementById('layout1');
const layout2 = document.getElementById('layout2');
layout2.classList.add('hidden');
let elm_cloned = layout1.cloneNode(true);
elm_cloned.querySelector('h1').textContent = 'Layout 2';
elm_cloned.querySelector('p').textContent = 'This is layout 2.';
layout2.innerHTML = '';
layout2.appendChild(elm_cloned);
button.addEventListener('click', function () {
if (active_layout === 1) {
layout1.classList.add('hidden');
layout2.classList.remove('hidden');
} else {
layout1.classList.remove('hidden');
layout2.classList.add('hidden');
}
active_layout = (active_layout === 1) ? 2 : 1;
});
});
.layout1,
.layout2 {
background-color: #f0f0f0;
padding: 20px;
margin: 10px;
}
.layout1.hidden,
.layout2.hidden {
display: none;
}
<button id="button">Switch Layout</button>
<div class="layout1" id="layout1">
<h1>Layout 1</h1>
<p>This is layout 1.</p>
</div>
<!-- Layout 2 -->
<div class="layout2" id="layout2">
<!-- Content of Layout 2 will be cloned from Layout 1 during runtime -->
</div>