Reputation: 13
I've been stuck for a few days. I can't fix my error, I tried adding .bind (this) but it doesn't work. Do you have any idea
errors : TypeError: can't access property "style", this.menu_indicator is undefined I will have an error on this line this.menu_indicator.style.left = this.menu_position + "px";
here is my code js , html , css
class TabBar {
constructor()
{
this.menu_bar = document.querySelector('.tab-bottom-bar');
this.menu_item = document.querySelector('.tab-menu-item');
this.menu_indicator = document.querySelector('.tab-nav-indicator');
this.current_item = document.querySelector('.tab-current');
this.menu_position;
}
initMenu()
{
this.menu_position = this.current_item.offsetLeft -16;
this.menu_indicator.style.left = this.menu_position + 'px;
this.menu_bar.style.backgroundPosition = this.menu_position -8 + 'px';
let parent = this.menu_item.parentElement;
Array.prototype.forEach.call(parent.children,
function(select_menu_item){
select_menu_item.addEventListener('click', function(e){
e.preventDefault();
this.menu_position = this.offsetLeft - 16;
this.menu_indicator.style.left = this.menu_position + 'px;
this.menu_bar.style.backgroundPosition = this.menu_position -8 + 'px';
[...select_menu_item.parentElement.children].forEach(
sibling => {
sibling.classList.remove('tab-current');
});
select_menu_item.classList.add('tab-current');
}.bind(this));
}
)
}
}
let menu_tab = new TabBar();
menu_tab.initMenu();
:root{
--primary-color:#0D6FFA;
--accent-color:#49CE95;
--danger-color:#EC3582;
--fore-color:rgba(0,0,0,0.65);
--main-cast-shadow: 0px 3px 12px rgba(0, 0, 0, 0.08), 0px 3px 6px rgba(0, 0, 0, 0.12);
}
body{
background-color:#D9D8D7;
}
.tab-bottom-bar{
position:absolute;
display:flex;
padding: 16px 36px;
justify-content:space-between;
width:335px;
margin:auto;
top:0;
left:0;
bottom:0;
right:0;
height: 32px;
font-size:26px;
background-image:radial-gradient(circle at 36px 6px,transparent 36px, #ffffff 37px);
filter: drop-shadow(0px -1px 6px rgba(0, 0, 0, 0.08)) drop-shadow(0px -2px 12px rgba(0, 0, 0, 0.12));
border-bottom-left-radius:30px;
border-bottom-right-radius:30px;
transition: cubic-bezier(0.57, 0.23, 0.08, 0.96) .45s;
}
.tab-nav-indicator{
position:absolute;
width: 56px;
height: 56px;
bottom: 28px;
margin: auto;
left: 0;
background-color: #000000;
box-shadow: var(--main-cast-shadow);
border-radius:50%;
transition: cubic-bezier(0.45, 0.73, 0, 0.59) .3s;
}
.tab-menu-item{
color:var(--fore-color);
transition:ease-in-out .5s;
cursor: pointer;
}
.tab-current{
position:relative;
color:#ffffff;
z-index:3;
transform:translate3d(-2px,-22px,0px);
}
<div class="tab-bottom-bar">
<a href="#" class="tab-menu-item tab-current"><i class="fas fa-home"></i></a>
<a class="tab-nav-indicator"></a>
<a href="#" class="tab-menu-item"><i class="fas fa-book-reader"></i></a>
<a href="#" class="tab-menu-item"><i class="fas fa-user-tie"></i></a>
<a href="#" class="tab-menu-item"><i class="fas fa-at"></i></a>
</div>
Upvotes: 0
Views: 719
Reputation: 13
it looks like it loses offsetLeft of the indicator shot does not move, I can't fix it.
Error fixed :)
class TabBar {
constructor()
{
this.menu_bar = document.querySelector('.tab-bottom-bar');
this.menu_item = document.querySelectorAll('.tab-menu-item');
this.menu_indicator = document.querySelector('.tab-nav-indicator');
this.menu_current_item = document.querySelector('.tab-current');
this.menu_position;
}
initMenu()
{
this.menu_position = this.menu_current_item.offsetLeft -16;
this.menu_indicator.style.left = this.menu_position + "px";
this.menu_bar.style.backgroundPosition = this.menu_position - 8 + 'px';
let that = this;
this.menu_item.forEach(function(select_menu_item) {
select_menu_item.addEventListener('click', function (e) {
e.preventDefault();
that.menu_position = this.offsetLeft -16;
that.menu_indicator.style.left = that.menu_position + "px";
that.menu_bar.style.backgroundPosition = that.menu_position - 8 + 'px';
[...select_menu_item.parentElement.children].forEach(
sibling => {
sibling.classList.remove('tab-current');
});
select_menu_item.classList.add('tab-current');
});
})
}
}
let menu_tab = new TabBar(); menu_tab.initMenu();
Upvotes: 0
Reputation: 10790
This is called this problem. When you nest functions as you do, you created nested scopes. In those scopes, this reference changes as the nesting goes. If you want to keep the reference you have 2 choices.
// this is different
Array.prototype.forEach.call(parent.children,
function(select_menu_item){
// than this
select_menu_item.addEventListener('click', function(e){
// and this is different than the other two
Solution 1
Array.prototype.forEach.call(parent.children,
(select_menu_item) => {
select_menu_item.addEventListener('click', e=> {
Solution 2
let that= this;
Array.prototype.forEach.call(parent.children,
function(select_menu_item){
select_menu_item.addEventListener('click', function(e){
// use that here.
Upvotes: 3