2

My Goal: To namespace my javascript to keep the global namespace clean.

My question: how do I share variables between methods in my JavaScript namespace?

In my example I am extending and overwriting the behaviour of the ASP.net ModalPopupExtender. I want to know how I can share the modalPopupStack variable with ModalPopupShowOverride and ModalPopupHideOverride without making it global.

Relevant code:

$(function () {
    if (Sys.Extended != undefined && Sys.Extended.UI != undefined && Sys.Extended.UI.ModalPopupBehavior != undefined) {
        MyPageMethods.ModalPopupShowOriginal = Sys.Extended.UI.ModalPopupBehavior.prototype.show;
        MyPageMethods.ModalPopupHideOriginal = Sys.Extended.UI.ModalPopupBehavior.prototype.hide;
        Sys.Extended.UI.ModalPopupBehavior.prototype.show = MyPageMethods.ModalPopupOverrides.ModalPopupShowOverride;
        Sys.Extended.UI.ModalPopupBehavior.prototype.hide = MyPageMethods.ModalPopupOverrides.ModalPopupHideOverride;
    }
});

var MyPageMethods = {

    ModalPopupShowOriginal: function () { },

    ModalPopupHideOriginal: function () { },

    ModalPopupOverrides: {

        modalPopupStack: new Array(),

        ModalPopupShowOverride: function () {

            var extender = this;
            var topElement;

            MyPageMethods.ModalPopupShowOriginal.apply(this, arguments);

            for (var x = 0; x < modalPopupStack.length; x++) {

                if ($(modalPopupStack[x].background).css("z-index") > $(extender._element).css('z-index') || $(modalPopupStack[x].popup).css("z-index") > $(extender._element).css('z-index')) {

                    if ($(modalPopupStack[x].background).css("z-index") > $(extender._element).css('z-index')) {
                        topElement = $(modalPopupStack[x].background).css("z-index");
                    }
                    else if ($(modalPopupStack[x].popup).css("z-index") > $(extender._element).css('z-index')) {
                        topElement = $(modalPopupStack[x].popup).css("z-index");
                    }

                }

            }

            if (topElement != undefined) {
                $(extender._backgroundElement).css('z-index', topElement);
            }

            modalPopupStack.push({ 'id': extender._id, 'background': extender._backgroundElement, 'popup': extender._element });

        },

        ModalPopupHideOverride: function () {
            var extender;
            MyPageMethods.ModalPopupHideOriginal.apply(this, arguments);
            extender = modalPopupStack.shift();
        }

    }

}

I'm sure there is a simple solution to this, but I'm not sure what it is.

1
  • Let there be a part of namespace where you can have variables which can be accessed by all the method namespaces. Commented Jul 6, 2012 at 19:10

3 Answers 3

4

It sounds like you want the variables to be visible within your namespace but not outside of it. If so then try the following solution.

var MyPageMethods = (function() { 
  // This variable is local to the namespace.  It can't be accessed from 
  // the caller
  var modalPopupStack = new Array();

  // These values are available to the callers as members of MyPageMethods
  return { 
    ModalPopupShowOriginal: function () { },

    ModalPopupHideOriginal: function () { },

    ModalPopupOverrides: { ... } 
  };
})();

This pattern uses a function to establish a private function scope for local variables of the namespace. It then returns a new object which contains the members accessible outside the namespace. Those definitions occur inside the function hence they can access the namespace private data.

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

1 Comment

+1 - if you truly want to restrict access to the value, then this is the way to go.
1

You can reference that property in both methods using:

MyPageMethods.ModalPopupOverrides.modalPopupStack

That can be a little bit cumbersome, so you'd likely want to alias it inside each method, like this:

var modalPopupStack = MyPageMethods.ModalPopupOverrides.modalPopupStack;

Note that the value is still visible in the global scope (unlike in @JaredPar's answer), but its merely piggy-backing on an existing global object.

Comments

0

Make it part of the namespace, if you like. Or for more privacy, make a local closure which incorporates it and exposes the functions you want:

var MyPageMethods = {
    ModalPopupShowOriginal: function () { },
    ModalPopupHideOriginal: function () { },
    ModalPopupOverrides: (function() {
        var modalPopupStack = new Array();
        var show = function () {
            // show implementation using modalPopupStack
        };
        var hide = function () {
            // hide implementation using modalPopupStack
        };
        return {
            ModalPopupShowOverride: show,
            ModalPopupHideOverride: hide
        }
    }())
};

By the way, it's pretty rare to use new Array() these days. This is usually preferred:

        var modalPopupStack = [];

It's shorter, cleaner, and really more explicit.

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.