4

I have a problem with a content overlay script I am developing. It seems that my closing event fires twice, but returns 'undefined' the first time (or second time, depending on which opening link you click).

You can find a stripped-down working example on JSFiddle: http://jsfiddle.net/UhSLy/2/

If you click on 1. Click and then on 2. Click it alerts undefined first, then Dummy.

When I delete one opening-link, everything works fine. But I have to have multiple links since they open different overlays.

What causes the problem and how can I avoid it?

Edit: Code from JSFiddle follows:

;(function ($, window, document, undefined) {

"use strict";

var pluginName = 'contentOverlay',
    defaults = {
        property:   'value'
    };

function Plugin(element, options) {
    this.element = element;
    this.$element = $(element);

    this.options = $.extend({}, defaults, options);

    this.init();
}

Plugin.prototype = {

    /**
     * Init
     */
    init: function () {
        var self = this;

        // Bind opening method
        this.$element.click(function() {
            self.open();
        });

        // Bind closing method
        $('#close').click(function() {
            self.close();
        });
    },

    /**
     * Open
     */
    open: function () {
        this.overlay = 'Dummy';
    },

    /**
     * Close
     */
    close: function () {
        alert(this.overlay); // <==== PROBLEM: fires twice. returns 'undefined' once
    },

};

$.fn[pluginName] = function (options) {
    return this.each(function () {
        if (!$.data(this, 'plugin_' + pluginName)) {
            $.data(this, 'plugin_' + pluginName,
                new Plugin(this, options));
        }
    });
}

$(function () {
    $('.open').contentOverlay();
});

})(jQuery, window, document);

5
  • When I run that it alerts Dummy twice. Commented Jul 9, 2012 at 23:29
  • @lwburk: I think that's the point. Commented Jul 9, 2012 at 23:31
  • 1
    Please paste the code from your Fiddle here. We have a lovely code editor, and it gets lonely when it is neglected. Commented Jul 9, 2012 at 23:32
  • @RobertHarvey - The point is that it runs twice, yes. That's not what I was pointing out. I thought he implied that the contents of the alerts were different. Commented Jul 9, 2012 at 23:35
  • When I run it in Chrome 20 and Firefox 11 it alerts 'undefined' first and then 'Dummy'. @lwburk Which browser are you using? Commented Jul 9, 2012 at 23:41

3 Answers 3

3
$('#close').click(function() {
    self.close();
});

You're binding both objects close() methods to the close handler. Basically, when you click on the close button, it's running two functions, one for each of the overlay objects. Because one overlay object doesn't exist, it's returning undefined.

You could get around this problem by:

close: function () {
    if(this.overlay != undefined){ // Skips over the undefined overlays
        alert(this.overlay);
    }
}

DEMO: http://jsfiddle.net/UhSLy/9/

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks, that makes sense. In that case I think my plugin design is flawed / I chose the wrong plugin pattern. How would you solve that? (Multiple opening links for different content overlays with only one closing button for all.)
@JohnB. Nopes plugin aint flawed :) see my explanation below, cheers guys!
0

If I may suggest look in here: http://jsfiddle.net/PgbfN/25/

I reckon your this if condition which is to check if plugin is initialised is undefined hence runs through twice.

To resolve I added isApplied flag, once applied set the flag to true. Rest hope demo will help :)

Hope it helps

$.fn[pluginName] = function(options) {
        return this.each(function() {
            alert('me ==> ' + (!$.data(this, 'plugin_' + pluginName)) + " ==== " + $.data(this, 'plugin_' + pluginName));
            if (!isApplied) {
                $.data(this, 'plugin_' + pluginName, new Plugin(this, options));

            }
        });
    }

full code

var isApplied = false;

(function($, window, document, undefined) {

    "use strict";

    var pluginName = 'contentOverlay',
        defaults = {
            property: 'value'
        };

    function Plugin(element, options) {
        this.element = element;
        this.$element = $(element);

        this.options = $.extend({}, defaults, options);
        isApplied = true;
        this.init();
    }

    Plugin.prototype = {

        /**
         * Init
         */
        init: function() {
            var self = this;

            // Bind opening method
            this.$element.click(function() {
                self.open();
            });

            // Bind closing method
            $(document).on('click', '#close', function() {
                alert('Close is clicked');
                //self.close(); //<<== Is called
            });
        },

        /**
         * Open
         */
        open: function() {
            this.overlay = 'Dummy';
        },

        /**
         * Close
         */
        close: function() {
            alert(this.overlay); // <==== PROBLEM: fires twice. returns 'undefined' once
        },

    };

   $.fn[pluginName] = function(options) {
        return this.each(function() {
            alert('me ==> ' + (!$.data(this, 'plugin_' + pluginName)) + " ==== " + $.data(this, 'plugin_' + pluginName));
            if (!isApplied) {
                $.data(this, 'plugin_' + pluginName, new Plugin(this, options));

            }
        });
    }

    $(function() {
        $('.open').contentOverlay();
    });

})(jQuery, window, document);

Comments

0

I've came up with this (only the changes here)

open: function () {
        this.overlay = 'Dummy';
        this.opened=true;
},

$('#close').click(function() {
    if(self.opened) 
    {
        self.opened=false;
        self.close();
    }    
});

I think code explains everything. The close event will never fire if an instance doesn't exist.

DEMO.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.