Exemplo n.º 1
0
AppWindow = Ribcage.extend({
  template: require('./template.hbs')
, className: 'pulse-app-window'
, events: {
    'click .js-chat': 'sendComment'
  , 'click .js-accomplishment': 'sendAccomplishment'
  , 'click .js-join': 'joinUs'
  , 'submit form': 'noop'
  , 'keyup .js-chat-input': 'handleChatKeyup'
  , 'keyup .js-accomplishment-input': 'handleAccomplishmentKeyup'
  , 'focus .js-accomplishment-input': 'handleAccomplishmentFocus'
  , 'blur .js-accomplishment-input': 'handleAccomplishmentBlur'
  }
, authenticated: false
, user: null
, afterInit: function () {
    var self = this;

    if(!socket)
      socket = io.connect('/');

    this.resetFormStash();

    this.timeline = new Timeline([]);
    this.timeline.on('error', App.handleError);

    this.timeline.fetch({
      success: function () {
        self.render();
      }
    });

    socket.on('news', function (data){
      self.$('.pulse-pane h3.user-count').text(parseInt(data, 10));
    });

    socket.on('accomplishment', function (data) {
      var accomplishment = new Accomplishment(Accomplishment.prototype.parse(data))
        , accomplishmentPane = self.$('.js-accomplishment-pane');

      self.timeline.add(accomplishment);
      self.prependSubview(new AccomplishmentView({model: accomplishment}), accomplishmentPane);
      self.scrollDown();
    });

    socket.on('comment', function (data) {
      var comment = new Comment(Comment.prototype.parse(data))
        , commentPane = self.$('.js-chat-pane');

      self.timeline.add(comment);
      self.appendSubview(new CommentView({model: comment}), commentPane);
      self.scrollDown();
    });

    socket.on('disconnect', function() {
      socket.socket.reconnect();
    });

    $.ajax('/whoami', {
      dataType: 'json'
    , statusCode: {
        200: function (data) {
          self.authenticated = true;
          self.user = new User(data);
        }
      }
    , complete: function () {
        self.render();
      }
    });
  }
, resetFormStash: function () {
    this.$('.js-chat-input').val('');
    this.$('.js-accomplishment-input').val('');

    this.formStash = {
      accomplishment: ''
    , chat: ''
    };

  }
, scrollDown: function () {
    var self = this;

    // Defer this, it doesn't work reliably on initial page load ):
    setTimeout(function () {
      var accomplishmentPane = self.$('.js-accomplishment-pane')
        , commentPane = self.$('.js-chat-pane');

      accomplishmentPane.scrollTop(0);
      commentPane.scrollTop(commentPane[0].scrollHeight);
    }, 300);
  }
, beforeRender: function () {
    // Stash form contents!
    this.formStash = {
      accomplishment: this.$('.js-accomplishment-input').val()
    , chat: this.$('.js-chat-input').val()
    };
  }
, afterRender: function () {
    var self = this
      , accomplishmentPane = this.$('.js-accomplishment-pane')
      , commentPane = this.$('.js-chat-pane');

    this.timeline.each(function (model) {
      if(model._name === 'Accomplishment')
        self.prependSubview(new AccomplishmentView({model: model}), accomplishmentPane);
      else {
        self.appendSubview(new CommentView({model: model}), commentPane);
      }
    });

    this.handleAccomplishmentBlur();

    if(this.formStash.accomplishment !== '')
      this.$('.js-accomplishment-input').focus();
    else
      this.$('.js-chat-input').focus();

    this.scrollDown();
  }
, sendComment: function () {
    var self = this
      , newComment = new Comment({
          text: this.$('.js-chat-input').val()
        })
      , tempSave;

    this.$('.js-chat-input').prop('disabled', true);

    newComment.on('error', function () {
      self.$('.js-chat-input').prop('disabled', false)
                              .val(tempSave);
    });

    tempSave = this.$('.js-chat-input').val();

    this.resetFormStash();

    newComment.save({}, {
      success: function () {
        self.$('.js-chat-input')
            .prop('disabled', false)
            .val('')
            .focus();
      }
    });
  }
, sendAccomplishment: function () {
    var self = this
      , newAccomplishment = new Accomplishment({
          text: this.$('.js-accomplishment-input').val()
        })
      , tempSave;

    this.$('.js-accomplishment-input').prop('disabled', true);

    newAccomplishment.on('error', function () {
      self.$('.js-accomplishment-input')
          .prop('disabled', false)
          .val(tempSave);
    });

    tempSave = this.$('.js-accomplishment-input').val();

    this.resetFormStash();

    newAccomplishment.save({}, {
      success: function () {
        self.$('.js-accomplishment-input')
            .prop('disabled', false)
            .val('').focus();
      }
    });
  }
, handleChatKeyup: function (e) {
    if (event.keyCode == 13 && !event.shiftKey)
        this.sendComment(e);
  }
, handleAccomplishmentKeyup: function () {
    var str = this.$('.js-accomplishment-input').val()
      , diff = str == null ? MIN_ACCOMPLISHMENT_LENGTH : MIN_ACCOMPLISHMENT_LENGTH - str.length;

    if(diff > 0) {
      this.$('.js-accomplishment').text(diff + ' more characters to go..').prop('disabled', true);
    }
    else {
      this.$('.js-accomplishment').text('Accomplish!').prop('disabled', false);
    }
  }
, handleAccomplishmentFocus: function () {
    this.handleAccomplishmentKeyup();
    this.$('.js-accomplishment').fadeIn(300);
  }
, handleAccomplishmentBlur: function () {
    var str = this.$('.js-accomplishment-input').val()
      , diff = str == null ? MIN_ACCOMPLISHMENT_LENGTH : MIN_ACCOMPLISHMENT_LENGTH - str.length;

    if(diff > 0)
      this.$('.js-accomplishment').hide();
    else
      this.$('.js-accomplishment').fadeIn(300);
  }
, joinUs: function (e) {
    e.preventDefault();
    e.stopPropagation();
    App.navigate('/authenticate', {trigger: true});
  }
, beforeClose: function () {
    this.timeline.off();
    delete this.timeline;

    socket.removeAllListeners();
  }
, noop: function (e) {
    if(e) {
      e.preventDefault();
      e.stopPropagation();
    }
  }
, context: function () {
    return {
      authenticated: this.authenticated
    , user: this.user ? this.user.toJSON() : {}
    , formStash: this.formStash
    };
  }
});
Exemplo n.º 2
0
AppView = Ribcage.extend({
  template: require('./app.hbs')
, quantity: 50
, unit: 'lb'
, afterInit: function () {
    var self = this;

    this.picker = new QuantityPicker({
      range: {low: 1, high: 1000}
    , step: 4
    , measure: 'mass'
    });

    this.listenTo(this.picker, 'change', function () {
      var pickerVals = self.context();

      self.$('.value').text(pickerVals.value);
      self.$('.unit').text(pickerVals.unit);
    });
  }
, afterRender: function () {
    var self = this;

    this.appendSubview(this.picker, this.$('.spinholder'));
    this.picker.render();
  }
, context: function () {
    var pickerVals = this.picker.getValues();

    return {
      value: pickerVals.quantity.value + pickerVals.division.value
    , unit: pickerVals.unit.value
    };
  }
});
Exemplo n.º 3
0
AppView = Ribcage.extend({
  template: require('./app.hbs')
, quantity: 50
, unit: 'lb'
, afterInit: function () {
    var i
      , ii
      , threes = {}
      , fours = {}
      , fives = {};

    for(i=1, ii=100; i<=ii; i++) {
      threes[i * 3] = i * 3;
    }

    for(i=1, ii=100; i<=ii; i++) {
      fours[i * 4] = i * 4;
    }

    for(i=1, ii=50; i<=ii; i++) {
      fives[i * 5] = i * 5;
    }

    this.quants = {
      threes: threes
    , fours: fours
    , fives: fives
    };

    this.picker = new Picker({
      slots: {
        quantity: {
          values: threes
        , style: 'right'
        , defaultKey: 60
        }
      , unit: {
          values: {
            Threes: 3
          , Fours: 4
          , Fives: 5
          }
        , style: 'right'
        }
      }
    });
  }
, afterRender: function () {
    var self = this;

    this.stopListening(this.picker);

    this.appendSubview(this.picker, this.$('.spinholder'));

    this.picker.render();
    this.picker.delegateEvents();

    this.listenTo(this.picker, 'change', function () {
      var pickerVals = self.context();

      self.$('.quantity').text(pickerVals.quantity);
      self.$('.unit').text(pickerVals.unit);
    });

    this.listenTo(this.picker, 'change:unit', function (newData) {
      switch(newData.key) {
        case 'Threes':
          self.picker.setSlot('quantity', {values: self.quants.threes});
        break;
        case 'Fours':
          self.picker.setSlot('quantity', {values: self.quants.fours});
        break;
        case 'Fives':
          self.picker.setSlot('quantity', {values: self.quants.fives});
        break;
      }
    });
  }
, context: function () {
    var pickerVals = this.picker.getValues();

    return {
      quantity: pickerVals.quantity.value
    , unit: pickerVals.unit.key
    };
  }
});
Exemplo n.º 4
0
AppWindow = Ribcage.extend({
  template: require('./template.hbs')
, className: 'pulse-app-window'
, events: {
    'click .js-comment': 'sendComment'
  , 'click .js-accomplish': 'sendAccomplishment'
  , 'click .js-join': 'joinUs'
  , 'keyup .js-entry-input': 'handleFormKeyup'
  , 'submit form': 'noop'
  }
, authenticated: false
, user: null
, afterInit: function () {
    var self = this;

    if(!socket)
      socket = io.connect('/');

    this.accomplishments = new Accomplishments([]);
    this.accomplishments.on('add remove change', function () {
      self.render();
      self.scrollDown();
    }, this);
    this.accomplishments.on('error', App.handleError);

    // Once accomplishments are loaded for the first time
    // , load the last one's comments
    this.accomplishments.once('sync', function () {
      if(self.accomplishments.length) {
        var last = self.accomplishments.last();

        // After the initial comment load completes it should scroll down
        last.once('comments:sync', self.scrollDown, self);

        last.loadComments();
      }
    });

    this.accomplishments.fetch();

    socket.on('accomplishment', function (data) {
      var accomplishment = new Accomplishment(Accomplishment.prototype.parse(data));

      self.accomplishments.add(accomplishment);
      accomplishment.loadComments();
    });

    socket.on('comment', function (data) {
      var lastAccomplishment = self.accomplishments.last();

      if(lastAccomplishment.commentsLoaded()) {
        lastAccomplishment.addComment(new Comment(Comment.prototype.parse(data)));
        self.scrollDown();
      }
    });

    socket.on('disconnect', function() {
      socket.socket.reconnect();
    });

    $.ajax('/whoami', {
      dataType: 'json'
    , statusCode: {
        200: function (data) {
          self.authenticated = true;
          self.user = new User(data);
        }
      }
    , complete: function () {
        self.render();
      }
    });
  }
, scrollDown: function () {
    var mainPane = this.$('.js-main-pane');
    mainPane.scrollTop(mainPane[0].scrollHeight);
  }
, afterRender: function () {
    var self = this
      , mainPane = this.$('.js-main-pane');

    this.$('.invalid-hint').hide();
    this.$('.incomplete-hint').hide();

    this.accomplishments.each(function (accomplishment) {
      self.appendSubview(new AccomplishmentView({model: accomplishment}), mainPane);
    });

    this.$('.js-entry-input').focus();
  }
, sendComment: function () {
    var self = this
      , newComment = new Comment({
          text: this.$('.js-entry-input').val()
        });

    newComment.on('error', function () {
      self.$('.enter-hint').hide();
      self.$('.invalid-hint').show();
      self.$('.incomplete-hint').hide();

      self.$('.js-entry-input').addClass('invalid').focus();
    });

    newComment.save({}, {
      success: function () {
        self.$('.enter-hint').show();
        self.$('.invalid-hint').hide();
        self.$('.incomplete-hint').hide();
        self.$('.js-entry-input').removeClass('invalid').val('').focus();
      }
    });
  }
, sendAccomplishment: function () {
    var self = this
      , newAccomplishment = new Accomplishment({
          text: this.$('.js-entry-input').val()
        });

    newAccomplishment.on('error', function () {
      self.$('.enter-hint').hide();
      self.$('.invalid-hint').show();
      self.$('.incomplete-hint').hide();

      self.$('.js-entry-input').addClass('invalid').focus();
    });

    newAccomplishment.save({}, {
      success: function () {
        self.$('.enter-hint').show();
        self.$('.invalid-hint').hide();
        self.$('.incomplete-hint').hide();
        self.$('.js-entry-input').removeClass('invalid').val('').focus();
      }
    });
  }
, joinUs: function () {
    App.navigate('/authenticate', {trigger: true});
  }
, handleFormKeyup: function (e) {
    if (event.keyCode == 13) {
      if(event.shiftKey)
        this.sendAccomplishment(e);
      else
        this.sendComment(e);
    }
  }
, beforeClose: function () {
    this.accomplishments.off();
    delete this.accomplishments;

    socket.removeAllListeners();
  }
, noop: function (e) {
    if(e) {
      e.preventDefault();
      e.stopPropagation();
    }
  }
, context: function () {
    return {
      authenticated: this.authenticated
    , user: this.user ? this.user.toJSON() : {}
    };
  }
});