Knight Yoshi
Knight Yoshi

Reputation: 994

JavaScript: Not Calling Constructor Function

Can someone shed some light as to why this doesn't work the way I think it should (or what I'm overlooking).

function Pane(data) {
    var state = {
        show: function(data) {
            var pane = document.querySelector('.pane[data-content='+data.target+']');
            pane.classList.add('active');
        },
        hide: function(data) {
            var pane = document.querySelector('.pane[data-content='+data.target+']');
            var paneSibling = $(pane.parentNode.childNodes);
            paneSibling.each(function(sibling) {
                if(check.isElement(sibling)) {
                    var isActive = sibling.classList.contains('active');
                    if(sibling != pane && isActive) {
                        sibling.classList.remove('active');
                    };
                };
            });
        }
    }
    return state;
}

So I can console log Pane(arg).show/hide and it'll log it as a function, so why is it when I call Pane(arg).show it doesn't do anything? The functions in the object work (outside of the constructor function in their own functions).

Upvotes: 0

Views: 85

Answers (2)

bfavaretto
bfavaretto

Reputation: 71918

The function is returning the state object, so it will never return the constructed object, even when used with new. Since state contains those methods, you can just call the function and immediately invoke one of the methods on the returned object.

Now, if you're expecting show and hide to automatically have access to data via closure, it's not working because you're shadowing the variable by declaring the method parameters. You can do this instead:

function Pane(data) {
    var state = {
        show: function() {
            var data = data || arguments[0];
            var pane = document.querySelector('.pane[data-content='+data.target+']');
            pane.classList.add('active');
        },
        hide: function() {
            var data = data || arguments[0];
            var pane = document.querySelector('.pane[data-content='+data.target+']');
            var paneSibling = $(pane.parentNode.childNodes);
            paneSibling.each(function(sibling) {
                if(check.isElement(sibling)) {
                    var isActive = sibling.classList.contains('active');
                    if(sibling != pane && isActive) {
                        sibling.classList.remove('active');
                    };
                };
            });
        }
    }
    return state;
}

Then you can use it like this:

Pane({}).show();

Or like this:

var p = Pane();
p.show();

Or force a new argument when needed:

p.show({foo:'bar'});

Upvotes: 1

Neikos
Neikos

Reputation: 1980

You are overriding the original argument in each function. So what you are doing is to find elements with the attribute data-content='undefined'

This obviously doesn't work.

So to fix this you should just remove the data argument in the show/hide function.

Here is a plnkr showing the problem and fix.

Upvotes: 1

Related Questions