开发者

Encapsulate javascript code in a global object for clearer code

I am trying to get things working using jQuery and jQueryUI's datepicker, inline mode.

I would like to put all my开发者_如何学Go code in a global object, and use it for datepicker init function (beforeShowDay, changeMonthYear). I also have a few utility functions.

I am stuck because I don't really know how to proceed.

I have read quite a few articles, tutorials, stackoverflow threads - especially on this scope, etc., but now I don't know where to start!

This is what I have so far:

var Calendar = (function() {
var obj = this;

var calendar = {
    datescache: [],
    bsd: function (date) {
        var offset =  this.formatNum(date.getMonth()+1)+'-'+this.formatNum(date.getDate());
        if (thedate[offset] != undefined) {
            return [true, 'bold', thedate[offset] + ' événement(s)'];
        } else {
            return [true];
        }
    },
    formatNum: function (i) {return ('0'+i).slice(-2);},
    getEventsForDate: function(year, month, inst) {
        var date = this.datescache;
        if (this.datescache[month] === undefined) {
            console.warn('uncached: '+month);
            $.ajax({
                url: '/event/get-event-count/year/'+year+'/month/'+month+'/format/json',
                success: function (resp) {
                    date[month] = resp.events;
                },
                async: false
            });
        }
        console.log('return: '+month);
        return date[month];
    }
}

return calendar;    
})();


$('#calendar').datepicker({
    dateFormat: "dd\/mm\/yy",
    showOtherMonths: true,
    selectOtherMonths: true,
    beforeShowDay: Calendar.bsd,
    onChangeMonthYear: Calendar.getEventsForDate,
});

Of course I have an error at the line:

var offset =  this.formatNum(date.getMonth()+1)+'-'+this.formatNum(date.getDate());  

because thisrefers to the datepicker object, as we are in a the callback function beforeShowDay that takes care passing the datepicker instance to the function as this. But I need this to refer to my utility functions, such as formatNum.

  • Where should I start ?
  • is it better to try to extend the datepicker object (not tried yet) ?

Thanks in advance for your help !

EDIT 1

OK, with some more readings and first answer, I managed to get something to work:

var Calendar = (function() {
  var calendar = function() {
    var self = this;

    this.datescache = [];

    this.bsd = function (date) {
       [[... I use for instance self.datescache ...  ]]
    }

    [[...]]

  };
  return new calendar();
})();

This seems to work fine.

  • Is the global encapsulation still needed ?

Thanks again !


For manipulation this in callback and other functions there are a few options.

Rather then calling this inside the function you can call an alias like that or self. In your case the variable obj = this is already an alias so you can call obj.formatNum

The other option is Function.bind which allows you to do this:

foo : (function() {
    ...
}).bind(obj),
...

Note that Function.bind is an ES5 thing. You can use _.bind or _.bindAll from underscorejs instead.

Another option to get the this scope to work is doing this

beforeShowDay: function() {
    Calendar.bsd();
},
onChangeMonthYear: function() {
    Calendar.getEventsForDate();
},

The difference here is rather then passing along a function (which when invoked will be invoked with a different this object) your passing along a function that invokes your function ON your own Calendar object thus forcing this to be Calendar.

See:

var f = function() { console.log(this); }
var a = {
    b: f
};
var c = {}
c.d = a.b;
c.e = function() {
    a.b();
};

f(); // window
a.b(); // a
c.d(); // c
c.e(); // calls a.b(); so a

this scope is whatever object you call the method on.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜