1

I'm pretty new to OOP concepts in general, and I'm trying to build this mini-application for a client. The idea is that it's supposed to have configurable options based on the Module number, etc. I've cut out some code to keep relevant stuff. I'm trying to make this as customizable as possible, in particular--allowing the coder to support multiple Lightbox-style popups by adding them to the options array below.

Everything has worked great until this--my issue is that I'm trying to bind each object in the options.popups array with jQuery, by feeding selector as a string in through the config, directly into a $() selector.

This works fine for binding click() to the opener, but the selector property just won't bind. Every time, I get this error: TypeError: self.options.popups[i] is undefined. If I directly insert the selector, e.g. $(".helpPopup").show();, it works fine. If I define it in a variable within the click() function directly above it, it works. e.g. var s = ".helpPopup";

Is there some obvious thing that I'm missing here? This is driving me nuts. Also, my code's design pattern is directly based off of this: https://github.com/shichuan/javascript-patterns/blob/master/jquery-plugin-patterns/prototypal-inheritance.html

Thanks!

var MODULE = {
    init: function(options, elem) {
        // Stuff here

        this.bindPopups();
    },

    options: {
        title: "Module title",
        pages: 1,
        currentPage: 1,
        windowOpener: ".popupVar",
        popups: [
            { 
                name: "help", 
                selector: ".helpPopup", 
                opener: ".button.open", 
                closer: ".button.close",
                type: 3
            }
        ]
    },

    bindPopups: function() {
        var self = this;

        for(i = 0; i < this.options.popups.length; i++) {
            // Open the popup
            $(self.options.popups[i].opener).click(function(e) {
                e.preventDefault();
                $(self.options.popups[i].selector).show();
            });

            // Close the popup
            $(self.options.popups[i].closer).click(function(e) {
                e.preventDefault();
                $(self.options.popups[i].selector).hide();
            });
        }
    }
};

// If browser doesn't support Object.create
if(typeof Object.create !== "function") {
    Object.create = function(o) {
        function F() {
            F.prototype = o;
            return new F();
        }
    };
}

// Create plugin
$.plugin = function(name, object) {
    $.fn[name] = function(options) {
        return this.each(function() {
            if(!$.data(this, name)) {
                $.data(this, name, Object.create(object).init(options, this));
            }
        });
    };
};

$.plugin("module", MODULE);



/* PAGE CODE */
<script>
    $(function() {
        $("body").module({
            title: "Module 1",
            pages: 12,
            popups: [
                { 
                    name: "help", 
                    selector: ".helpPopup", 
                    opener: ".button.open", 
                    closer: ".button.close",
                    type: 3
                },
                {
                    name: "info",
                    selector: ".infoPopup",
                    opener: ".button.info",
                    closer: ".button.close",
                    type: 1
                }
            ]
        });
    });
</script>
4

1 回答 1

0

出于某种原因,您i的 click 函数内部正在递增。为了验证,console.log(i);在点击事件函数之前放置一个,在打开的点击函数内部放置一个。

我不知道它为什么这样做(我没有看到任何明显的错误),但一个快速的技巧是var j = i;在你打开for循环后立即放置,并j用作你的索引选择器。

编辑:上面的 hack 只适用于一次迭代。“i似乎”在此处递增,因为直到for循环关闭后才对其进行评估,此时i已递增(对于单击事件)。例如,您可以通过在函数i内部登录来验证这一点。setTimeout

要获得 的适当值i,您必须将 click 事件函数包装在匿名函数中,如下所示:

$(self.options.popups[i].opener).click(
    (function (i) { 
        return function(e) {
            e.preventDefault();
            $(self.options.popups[i].selector).show();
        }
    })(i)
);

了解更多信息

于 2013-01-20T00:36:36.687 回答