brokethebuildagain
brokethebuildagain

Reputation: 2191

Triggering a Backbone.js event when the current date changes

Is there a simple way to trigger a Backbone.js event when the current date (just the day, not the time) changes?

Upvotes: 2

Views: 1609

Answers (3)

Andrey Kuzmin
Andrey Kuzmin

Reputation: 4479

You may create constructor that extends Backbone Events like this:

var Clocks = function(){};

_.extend(Clocks.prototype, Backbone.Events, {

  start: function () {
    this.timer = setInterval(_.bind(this.tick, this), 1000);
    return this;
  },

  tick: function () {
    this.trigger('tick', new Date)
  },

  stop: function () {
    this.timer && clearInterval(this.timer);
    return this;
  }

});

And then use it in backbone model to update it attributes:

var ClocksModel = Backbone.Model.extend({

  defaults: function () {
    var date = new Date
    return {
      date: date.getDate(),
      seconds: date.getSeconds()
    }
  },

  initialize: function () {
    this.clocks = new Clocks;
    this.clocks.on('tick', this.updateDate, this)
  },

  updateDate: function (date) {
    this.set('date', date.getDate())
    this.set('seconds', date.getSeconds())
  },

  start: function () {
    this.clocks.start();
    return this;
  },

  stop: function () {
    this.clock.stop();
    return this;
  }

});

Then you'll be able to:

clocks = new ClocksModel;
clocks
  .on('change:seconds', function(model, newSeconds) {
    console.log('seconds changed to ', newSeconds)
  })
  .on('change:date', function(model, newDate) {
    console.log('date changed to', newDate)
  })
  .start()

Upvotes: 2

Nirvana Tikku
Nirvana Tikku

Reputation: 4205

So, the answer to the question - there is no simple way without rolling your own solution.

That said, the implementation isn't too bad.

The idea here is that you have a model with a 'day' property. Upon initializing the model, we'll invoke an initializer that will determine the duration till 'midnight tomorrow'. Right after midnight, the setTimeout will get called which will update the model's 'day' property. In the view itself, we listen for a change for the 'day' property. Once the property is updated, we'll re-initialize the method that changes the date. This way there's no polling, and your events will be triggered once the date changes.

Of course there are numerous ways you could broadcast the update - i.e. explicitly trigger the event as opposed to seting the property -- but here's the code for what I've described above:

Model

var Model = Backbone.Model.extend({
    defaults: function(){
        var d = new Date();
        return {
            day: d.getDay()
        }
    },
    initialize: function(){
        _.bindAll(this, '_init_date_trigger');
        this._init_date_trigger();
    },
    _init_date_trigger: function(){
        var now = new Date();
        var midnightTomorrow = new Date();
        midnightTomorrow.setDate(now.getDate() + 1);
        midnightTomorrow.setHours(0,0,0,0);
        var msTillTomorrow = midnightTomorrow - now + 1;
        var me = this;
        console.log("date will be changed in " + msTillTomorrow);
        setTimeout(function(){
            me.set("day", new Date().getDay());
            me._init_date_trigger();
        }, msTillTomorrow);
    }
})

View

var View = Backbone.View.extend({
    template:_.template("The day is: <span class='day'> <%= day %> </span>"),
    initialize: function(){
        this.model.on("change:day", this.render);
    },
    render: function(){
        this.$el.html( this.template( this.model.toJSON() ) );
        return this;
    }
});

Implementation

var myModel = new Model();
var myView = new View({model: myModel});
$("#example").html( myView.render().el );

Here's the fiddle: http://jsfiddle.net/6KGzt/4/

Upvotes: 4

kapa
kapa

Reputation: 78731

I don't have a better idea than checking regularly:

var lastCheckedDate = new Date();
setInterval(function () {
    var d = new Date();
    //TODO: check whether the day in d and lastCheckedDate are the same or not
    //TODO: if not, trigger event
    lastCheckedDate = d;
}, 10000); //this will check in every 10 seconds

Upvotes: 2

Related Questions