2

Every time I invoke Client2.config.select2() everything is getting redefined.

Is there a way to prevent the re-definition of such an function/object? I.e. if I wanted to have another variable which saves some elements within this object, running Client2.config.select2() would override it.

Is there a well-known pattern to do this?

Client2.config.select2 = function() {

    var coreIDs    =  ['clientID', 'cptyID' , 'sym'];

    var nonCoreIDs =  ['groupBy','groupBy_impact_1','groupBy_impact_2',
        'groupBy_impact_3','groupBy_impact_4'];

    //non dynamic filters 
    var autoCompleteSettings =  function () {
        return {
            allowClear : true,
            minimumInputLength : 2,
            multiple : true,
            placeholder: "Select ",
            closeOnSelect : false,
            openOnEnter : true,
            ajax: {
                url : "../my?page=search",
                dataType : 'json',
                data : function(term, page) {
                    return {
                        q : term
                    };
                },
                results : function(data, page) {
                    return {
                        results : data
                    };
                }
            }
        };
    };

    var multipleSettings = function () {
        return {
            placeholder : "Select ",
            allowClear : true,
            closeOnSelect : false,
            maximumSelectionSize: 6
        };
    };

    return {
        getAutoCompleteSelectSettings: function() {
            return new autoCompleteSettings();
        },
        getMultipleSelectSettings: function() {
            return new multipleSettings();
        },
        getCoreSelect2IDs: function () {
            return coreIDs;
        },
        getNonCoreSelect2IDs: function () {
            return nonCoreIDs;
        },
        getSelect2IDs : function() {
            return coreIDs.concat(nonCoreIDs);
        }
    }
};
Rick Hanlon II
  • 20,549
  • 7
  • 47
  • 53
kkudi
  • 1,625
  • 4
  • 25
  • 47
  • What do you mean by "everything"? The variables like "coreIDs" declared inside the function? If you don't want them reinitialized, just move the declarations outside the function. – Pointy Sep 25 '13 at 12:33
  • [This answer](http://stackoverflow.com/questions/1535631/static-variables-in-javascript) might provide some pointers in the right direction – Bojangles Sep 25 '13 at 12:34

3 Answers3

3

You should use the module pattern: http://www.adequatelygood.com/JavaScript-Module-Pattern-In-Depth.html

An example of this is:

(function (CkSpace, $, undefined) {
    CkSpace.GetLoanValues = function () { //public member
       //Do Stuff
    }
    var myNumber = 1; //private member

} (window.CkSpace = window.CkSpace || {}, jQuery));
BenM
  • 4,218
  • 2
  • 31
  • 58
  • This is pretty over the top for solving the OPs problem in isolation, although if there's a lot of JS being used it's a good idea – Bojangles Sep 25 '13 at 12:35
  • I would argue it's not over the top as it provides the ability to stop things being redfined as well as adding in greater encapsulation and restricted access to members of the module. It's incredibly easy to implement this pattern and would require only a couple more lines of code for kkudi to add. – BenM Sep 25 '13 at 12:37
  • 1
    Cheers @BenM. all I had to do was make the function self-invoking and then I have a reference to Client2.config.select2 with all I need. This keeps the state as I want. Thanks for swift reply – kkudi Sep 25 '13 at 12:56
  • I agree with @Bojangles. All you need is to use closure to define the variables your want to define once inside the encapsulated function, which is easier to implement than this (see my answer). This sounds like what you did. – Rick Hanlon II Sep 25 '13 at 13:01
2

You can do this using closures.

Essentially, you're going to set Client2.config.select2 equal to an immediate function, define your variables inside of the immediate function (which are assigned once), and use closure to access those once-defined variables inside of the function which is returned.

Client2.config.select2 =  (function() {                              /* 1 */

    var coreIDs    =  ['clientID', 'cptyID' , 'sym'];                /* 2 */

    var nonCoreIDs =  ['groupBy','groupBy_impact_1','groupBy_impact_2',
        'groupBy_impact_3','groupBy_impact_4'];

    //non dynamic filters 
    var autoCompleteSettings =  function () {
        return {
            allowClear : true,
            minimumInputLength : 2,
            multiple : true,
            placeholder: "Select ",
            closeOnSelect : false,
            openOnEnter : true,
            ajax: {
                url : "../my?page=search",
                dataType : 'json',
                data : function(term, page) {
                    return {
                        q : term
                    };
                },
                results : function(data, page) {
                    return {
                        results : data
                    };
                }
            }
        };    
    };    

    var multipleSettings = function () {
        return {
            placeholder : "Select ",
            allowClear : true,
            closeOnSelect : false,
            maximumSelectionSize: 6
        };
    };

    return function (){                                              /* 3 */
        return {
            getAutoCompleteSelectSettings: function() {
                return new autoCompleteSettings();
            },
            getMultipleSelectSettings: function() {
                return new multipleSettings();
            },
            getCoreSelect2IDs: function () {
                return coreIDs;
            },
            getNonCoreSelect2IDs: function () {
                return nonCoreIDs;
            },
            getSelect2IDs : function() {
                return coreIDs.concat(nonCoreIDs);
            }
        }
    }
})();

In (1) you see that we're wrapping the function like this:

(function(){ 
    /* ... */ 
})();

If you don't know, this is called an immediate function because it is executed immediately when it is reached. This means that this function runs once.

In (2) we're defining all the the variables you want defined once, once, inside the scope of the immediate function. Again, using closure you'll be able to access these variables in the returned function below.

In (3) we're having the immediate function return a function, which returns the object you wanted to return. When you access, say, getAutoCompleteSelectSettings then you will return autoCompleteSettings from inside the immediate function.

Essentially you can think of it like this. After the immediate function runs, we have defined the assignment like this (because this is what the immediate function returned):

Client2.config.select2 = function (){
    return {
        getAutoCompleteSelectSettings: function() {
            return new autoCompleteSettings();
        },
        getMultipleSelectSettings: function() {
            return new multipleSettings();
        },
        getCoreSelect2IDs: function () {
            return coreIDs;
        },
        getNonCoreSelect2IDs: function () {
            return nonCoreIDs;
        },
        getSelect2IDs : function() {
            return coreIDs.concat(nonCoreIDs);
        }
    }
}

And each of the Objects and variables we're accessing here are accessible through reference in the immediate function.

Rick Hanlon II
  • 20,549
  • 7
  • 47
  • 53
0

Have you ever tried const keyword?

BAD_SEED
  • 4,840
  • 11
  • 53
  • 110