certainstrings
certainstrings

Reputation: 287

Multiple click handlers for a single element

I've written a few events to handle opening and closing of a snap js drawer. This code below works, but I feel it could be written more efficiently. Any suggestions?

function openMobileMenu() {
    event.preventDefault();
    snapper.open('left');
    $('#btn-menu').off('click', openMobileMenu);
    $('#btn-menu').on('click', closeMobileMenu);
}

function closeMobileMenu() {
    event.preventDefault();
    snapper.close('left');
    $('#btn-menu').on('click', openMobileMenu);
    $('#btn-menu').off('click', closeMobileMenu);
}

$('#btn-menu').on('click', openMobileMenu);

Upvotes: 0

Views: 97

Answers (3)

plalx
plalx

Reputation: 43718

Make your code modular and your concepts explicit.

You can start by creating a MobileMenu object which encapsulates the logic.

Note: The following code was not tested.

var MobileMenu = {
    _snapper: null,
    _$button: null,
    _direction: 'left',
    init: function (button, snapper, direction) {
        this._$button = $(button);
        this._snapper = snapper;
        if (direction) this._direction = direction;

        this._toggleSnapperVisibilityWhenButtonClicked();
    },
    _toggleSnapperVisibilityWhenbuttonClicked: function () {
        this._$button.click($.proxy(this.toggle, this));
    },
    toggle: function () {
        var snapperClosed = this._snapper.state().state == 'closed',
            operation = snapperClosed? 'open' : 'closed';

        this._snapper[operation](this._direction);
    }
};

Then in your page you can just do the following to initialize your feature:

var mobileMenu = Object.create(MobileMenu).init('#btn-menu', snapper);

Modularizing your code will make it more maintainable and understandable in the long run, but also allow you to unit test it. You also gain a lot more flexibily because of the exposed API of your component which allows other code to interact with it.

E.g. you can now toggle the menu visibility with mobileMenu.toggle().

Upvotes: 1

Roamer-1888
Roamer-1888

Reputation: 19298

snap has a .state() method, which returns an object stuffed with properties, one of which is .state.

I think you want :

$('#btn-menu').on('click', function() {
    if(snapper.state().state == "closed") {
        snapper.open('left');
    } else {
        snapper.close('left');
    }
});

Or, in one line :

$('#btn-menu').on('click', function() {
    snapper[['close','open'][+(snapper.state().state == 'closed')]]('left');
});

Also, check How do I make a toggle button? in the documentation.

Upvotes: 1

Barmar
Barmar

Reputation: 780723

Use a variable to keep track of the state:

var menu_open = false;
$("#btn-menu").on('click', function(event) {
    event.preventDefault();
    if (menu_open) {
        snapper.close('left');
    } else {
        snapper.open('left');
    }
    menu_open = !menu_open; // toggle variable
});

Upvotes: 1

Related Questions