Herbie Vine
Herbie Vine

Reputation: 2025

Event Listener assigned to parent div stops on button

I have a list of buttons to login and want to assign an event listener to them for a p5.js hover effect. I wanted to assign it to the wrapper, but when switching between buttons, it doesn't detect the hover.

I'm also using Vue.js v2.6.11

<div class="main">
    <div class="google hover">
        <button @click="loginWithProvider('google')">
            Login with Google
        </button>
    </div>
    <div class="twitter hover">
        <button @click="loginWithProvider('twitter')">
            Login with Twitter
        </button>
    </div>
    <div class="github hover">
        <button @click="loginWithProvider('github')">
            Login with GitHub
        </button>
    </div>
</div>

And the event listener:

1st version

const main = document.querySelector('.main');
main.addEventListener('mouseenter', () => {
    isHovered = true;
});
main.addEventListener('mouseout', () => {
    isHovered = false;
});

2nd version:

const buttons = document.querySelectorAll('.hover');

buttons.forEach(button => {
    button.addEventListener('mouseenter', () => {
        isHovered = true;
    });
});
buttons.forEach(button => {
    button.addEventListener('mouseout', () => {
        isHovered = false;
    });
});

Both had the same effect. Worked on enter, but once I stopped hovering over a button and went onto another (staying in the parent div, mouseout got triggered and didn't enter again for the other buttons (unless I went outside the parent div)

Upvotes: 0

Views: 51

Answers (2)

Asimple
Asimple

Reputation: 650

First of i think it would be better to render buttons with v-for, not manually, like here, then you can use events from Vue, and use them for hover events:

<div class="main">
    <div 
        v-for="(item,i) in loginList"
        :key="'login-list-' + i"
        :class="item.class"
        @mouseenter="hoverEntered"
        @mouseleave="hoverLeaved"
    >
        <button @click="loginWithProvider(item.provider)">
            <i :class="item.icon"></i>
            {{ item.text}}
        </button>
    </div>
</div>

And Vue code will look like:

data: () => ({
    isHovered: false,
    loginList: [
        {
            class: 'twitter hover',
            icon: 'fab fa-twitter',
            text: 'Login with twitter',
            provider: 'twitter'
        },
        {
            class: 'github hover',
            icon: 'fab fa-github',
            text: 'Login with github',
            provider: 'github'
        },
        {
            class: 'google hover',
            icon: 'fab fa-google',
            text: 'Login with google',
            provider: 'google'
        }
    ]
}),
methods: {
    hoverEntered() {
        this.isHovered = true; //isHovered = true; if u need non Vue var
    },
    hoverLeaved() {
        this.isHovered = false; //isHovered = true; if u need non Vue var
    }
}

So you will have less non-Vue code and it would be more predictable.

Upvotes: 0

Herbie Vine
Herbie Vine

Reputation: 2025

Turns out, adding a margin triggers the mouseenter & mouseout event. I just added a spacer div like this:

<div class="main">
    <div class="google hover">
        <button @click="loginWithProvider('google')">
            <i class="fab fa-google"></i>
            Login with Google
        </button>
    </div>
    <div class="spacer"></div>
    <div class="twitter hover">
        <button @click="loginWithProvider('twitter')">
            <i class="fab fa-twitter"></i>
            Login with Twitter
        </button>
    </div>
    <div class="spacer"></div>
    <div class="github hover">
        <button @click="loginWithProvider('github')">
            <i class="fab fa-github"></i>
            Login with GitHub
        </button>
    </div>
</div>

And edited my css:

// Removed
.button {
  margin-buttom: 10px;
}

// Added
.spacer {
  height: 10px;
}

Upvotes: 1

Related Questions