Skip to content

Instantly share code, notes, and snippets.

@raphaeleidus
Created August 24, 2012 16:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save raphaeleidus/3452495 to your computer and use it in GitHub Desktop.
Save raphaeleidus/3452495 to your computer and use it in GitHub Desktop.
Object-Oriented JS and Private Messaging

Use GistDeck to View

Why is this important?

  • OO Code is maintainable
  • loosely or unstructured JS code begets more unstructured code
  • Preventing from contact-list.js from ever happening again
  • Maintainability

Maintainability

  • Javascript is notoriously unmaintainable
  • Additions and changes can be inserted seemingly at random
  • jQuery relient functions can break when the html changes
  • OOP provides clear expectations and guidelines for where changes should be made

Why not use a framework?

  • With so many incredible frameworks that do OO well, why not just choose one?

  • We dont really need it, we can write good JS without it

  • Frameworks come with complex mental models and a bit of magic that can be difficult to learn

How did I write the Private Messages code

Overall it is coded with the observer pattern

a few main components

  • Models
  • Collections
  • Views
  • Global Emitter Instance
  • Templates

Rules for my style

  • Data logic goes in Models and Collections
  • Only views contain DOM event handlers
  • No global jQuery selectors are used in Views
  • All communication between objects goes through the Emitter Instance

The Code

Models/Collections

  • These are the components that deal with data.
  • At initialization they only start observing
PP.PrivateMessages.PrivateConversation = function(event_id) {
  this.event_id = event_id,
  this.url = '/api/v1/private_messages',
  this.before_id = 0;
  this.initializeObservations();
};

Model Functions

  getMessages: function() {
    var that = this;
    //server request
    this.requestJSON('GET',
      {
        'event_id': this.event_id,
        'partner_id': this.partner.messager_id,
        'partner_type': this.partner.messager_type,
        'before_id': this.before_id
      },
      function(response){
        that.messages = that.messages.concat(response.private_messages);
        if(that.messages[0]) {
          that.partner = PP.PrivateMessages.findPartner(that.messages[0]);
        }
        PP.PrivateMessages.Dispatcher.emit("conversationLoaded", response.private_messages, that.partner);
        PP.PrivateMessages.Dispatcher.emit("conversationActive", that.partner);
      }
    );
  }

Model Functions (continued)

Listen to the emitter

  initializeObservations: function() {
    var that = this;
    // observe for when something tries to send a message
    PP.PrivateMessages.Dispatcher.on("sendMessage", function(message_text){
      that.sendMessage(message_text);
    });
    // observe for requests to get a new conversation
    PP.PrivateMessages.Dispatcher.on("openConversation", function(partner){
      that.partner = partner;
      that.getMessages();
    });
    // observe for when the next batch of messages is needed
    PP.PrivateMessages.Dispatcher.on("loadMoreMessages", function() {
      that.getMessages({append: true});
    });
  }

Views

  • Deal with templates and handle user interaction
PP.PrivateMessages.ConversationCardView = function(message) {
  message.timestamp = PP.dateToString(message.created_at);
  this.message = message;
  this.message.partner = PP.PrivateMessages.findPartner(message);
  this.message.unread = (this.message.partner === this.message.recipient)? false : this.message.unread;
  this.template = templates.ConversationCardView;
  this.initializeObservations();
};

More View Code

  render: function() {
    this.$el = $(Mustache.to_html(this.template, this.message));
    this.attachDomEvents();
    return this.$el;
  },
  attachDomEvents: function() {
    var that = this;
    //catch when the conversation card has been clicked
    this.$el.on("click", function() {
      PP.PrivateMessages.Dispatcher.emit("openConversation", that.message.partner);
      //remove the unread icon from the conversation
      that.$el.find('.secondary').remove();
    });
  },
  initializeObservations: function() {
    var that = this;
    PP.PrivateMessages.Dispatcher.on("conversationActive", function(partner){
      that.$el.toggleClass('active', _.isEqual(partner, that.message.partner));
    });
  }

The Emitter

  • The emitter is my style's Sriracha Sauce
  • All communication that could possibly be done through the emitter is done through the emitter

Where did this style come from?

It's Backbone.js without the framework

Some of the niceties and magic are stripped out, but the result is more modular and encapsulated then the majority of Backbone code

fin

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment