Event driven approach

Have said it before and will say it again.. the people on StackOverflow are AWESOME! Got a REALLY useful overview of the Event Driven Approach and how it applies to backbone too. I was concerned that having to do everything in the .complete callback was going to mean lots of overhead in terms of calling multiple syncs/fetches.  http://stackoverflow.com/questions/27755976/backbone-js-reduce-calls-to-the-server/27756807

So now I’m changing things up a bit in my app to use the Event Aggregator to pass the information out of the fetch method into other functions where its needed (without doing another call to an external site)

As an update of where I am this far below. Loads more to do but I’m feeling like its definitely starting to take a better shape now! Whoop!

$( document ).ready(function() {

window.APP = {}
APP.vent = _.extend({},Backbone.Events);

/*
  ***********
  Models
  ***********
*/
var MatchInfo = Backbone.Model.extend({
  defaults: {
    season:"1415"
  }
});//model class

var matchInfo = new MatchInfo(); //model instance


/*
  ***********
  Collections
  ***********
*/

    var Matches = Backbone.Collection.extend({
      model: MatchInfo, //note this references the model class, not the model instance
      url : "http://www.hookhockey.com/index.php/temp-gillian/",
      sync : function(method, collection, options) {
        // By setting the dataType to "jsonp", jQuery creates a function
        // and adds it as a callback parameter to the request, e.g.:
        // [url]&callback=jQuery19104472605645155031_1373700330157&q=bananarama
        // If you want another name for the callback, also specify the
        // jsonpCallback option.
        // After this function is called (by the JSONP response), the script tag
        // is removed and the parse method is called, just as it would be
        // when AJAX was used.
        //console.log('sync');
        options.dataType = "jsonp";
        return Backbone.sync(method, collection, options);
      },
      parse : function(response) {
       // console.log(response.matches);
       //.matches is what the json at http://www.hookhockey.com/index.php/temp-gillian/ is putting out 
        return response.matches;

      },
      customFilter: function(filters){
        var results = this.where(filters);
        return new Matches(results);
      }

    }); //collection class
    var matches = new Matches(); //collection instance



/*
  ***********
  Views
  ***********
*/

    //model view
    var MatchModelView = Backbone.View.extend({
      tagName: 'li',
      template: _.template( $("#matchTemplate").html() ), // uses underscore and the content from index.html script tag with the id of matchElement that contains the template tags

      initialize: function () {

             },
      render: function() {
        var matchTemplate = this.template(this.model.toJSON()); //passes in all of the model data (using this.model.toJSON()) into the template (this.template) so that info is available to the template tags
        this.$el.html(matchTemplate); //pass the templated info into the el element and return it for render
        return this;
      }
    }); //model view class


    var matchView = new MatchModelView (); //model view instance

    //collection view class
    var MatchesModelView = Backbone.View.extend({
              tagName: 'div',
              events: {
                  "click .hello": "checkit",
                  "click .leagues a" : "leagues",
                  "change .dates" : "dates",
                  "click .home" : "render",
              },
              initialize: function () {
                      _.bindAll(this, "render");
                       this.collection.bind("reset", this.render);
                    
              },
              render: function(showit){
                    
                  if(this.collection == undefined){
                    console.log('undef'); //it'll be undefined if the sync hasn't finished yet
                   }

                  // this.collection.each(this.oneMatch, this);     
                  return this; //make the renders chainable
              },
              renderA : function(){
                    console.log('render A');
                    $('#a', this.$el).html('heyA');
                    return this; //make the renders chainable

              },
              renderB : function(){
                    console.log('render B');
                    $('#b', this.$el).html('heyB');
                    return this; //make the renders chainable
              },             
              senditout: function(showit){
                  if(this.collection == undefined){
                    console.log('undef'); //it'll be undefined if the sync hasn't finished yet
                   }
                   console.log('yup');
                  this.collection.each(this.oneMatch, this);                            
                  return this;
              },
              oneMatch: function (aMatch){
                //this is the function to render all the individula models
                  var matchView = new MatchModelView ({ model: aMatch });
                  this.$el.append(matchView.render().el);
                  return this
              },
              checkit: function(){
                //this will bring back all of the items that are matching data-1: data-2
                      var prop =  $(event.target).attr('data-1');
                      var val =  $(event.target).attr('data-2');
                      newCollection(this.collection, prop,val);

              },
              leagues: function(e){
                  // e.preventDefault();
                  console.log('leagues');
                    var val =  $(event.target).attr('href').replace('#','');
                    //var val = [18, 20]
                    newCollection(this.collection, "league", val);
              },
              dates: function(){
                console.log('dates');
                var mydate = $('.dates option:selected').val();
                newCollection(this.collection, "matchDate", mydate);
              }

    });  //end collection view class



//note: render should be called on the view after it has been instantiated

//these functions are getting called from events within the view

//this function is doing almost all of the filtering, its called from multiple events with different params
var newCollection = function(myCollection,prop,val){
    var results = myCollection.where(_.object([prop], [val]));
    var filteredCollection = new Backbone.Collection(results); //create a new collection from the results
    var newMatchesModelView = new MatchesModelView({collection: filteredCollection });
    $("#allMatches").html(newMatchesModelView.senditout().el);
 }




/* Fetching */
//trying to only fetch once so there aren't multiple calls to the server. So its only done on the index page


  //matches is a collection, fetch will go to the server and pull down the information
                    matches.fetch({
                            async:false, //may or may not use this
                            success : function(collection, response, options) {
                             /* notes: calling these outside of the success listener meant that nothing got returned. This is because they fire before the fetch returns http://stackoverflow.com/questions/9431673/load-data-into-a-backbone-collection-from-json-file
                             the alternative is to call them within the success function or to call them like so:
                             .complete(function() {
                                  console.log(matches);
                                  console.log('length: ' + matches.length);
                              });
                             
                             ..after the fetch call.

                             */
                              //console.log(matches);
                             return matches;
                        
                            },
                            error : function(collection, response, options) {
                              console.log(response.statusText);
                            },
                            // A timeout is the only way to get an error event for JSONP calls!
                            timeout : 5000
                        }).complete(
                              function(){
                                //sending my populated collection to the event aggregator
                                APP.vent.trigger("matchesCollectionLoaded:event", matches);
                              }

                        );//end complete




          /* functions for producing initial links */
          getLeagues = function(leagues){

              //output the list of unique leagues into an array
              var myArray = JSON.parse(JSON.stringify(leagues));
           
              for(i = 0; i < myArray.length; i++){
                var current = myArray[i];
                var button = '<li class="division"><a href="#'+current+'">Division '+current+'</a></li>'
                $('.leagues').append(button);
              }

              matchesModelView.$el.prepend($('.leagues'));

          };

          getMatchDates = function(dates){

              //output the list of unique leagues into an array
              var myArray = JSON.parse(JSON.stringify(dates));
           
              for(i = 0; i < myArray.length; i++){
                var current = myArray[i];
                var button = '<option value="'+current+'">'+current+'</option>'
                $('.dates').append(button);
              }

              matchesModelView.$el.prepend($('.dates'));

          };

 

          /* ./functions */

          //collection view is instantiated
          var matchesModelView = new MatchesModelView({collection: matches });
          matches.bind("sync", matchesModelView.render, matches); //is this still neccesary?



/*
  ***********
  Routers
  ***********
*/

var fetched;
MyRouter = Backbone.Router.extend({
          routes: {
          "" : "index",
          ":id": 'league'
          },
          index: function(){
              APP.vent.trigger("matchesCollectionLoaded:event", matches);
          }, //end of index root

          league: function(id){
            console.log('rooting' + id);

          //matchesModelView.leagues()
            //need to figure out how to dynamically create routes
          }

})

var myRouter = new MyRouter();
Backbone.history.start();

// end routing


/*
  ***********
  Events
  ***********
*/
// event aggregator - this listens for the event triggered in the fetch complete before running
APP.vent.on("matchesCollectionLoaded:event", function(matches){

                                  //clear it out first
                                  $("#allMatches").html('');

                                  console.log("matchesCollectionLoaded:event");
                                  //console.log(matches.toJSON());
                                  //create the initial buttons
                                  //pull the unique leagues out
                                    var uniqueLeagues = _.uniq(matches.pluck("league")); //the populated collection is accessible here
                                  //pull the unique leagues out   
                                     var uniqueDates = _.uniq(matches.pluck("matchDate"));

                                  //pass to info to the relative functions to create buttons   
                                     getLeagues(uniqueLeagues);
                                     getMatchDates(uniqueDates);
                                   
                                     fetched = true;

                                     //mytest(matches); // can throw out to other functions now

                                    $('.hello').on("click", function(){
                                    APP.vent.trigger("futureGames:event", matches);
                                    });

                                    $('.home').on("click", function(){
                                    APP.vent.trigger("homeBtn:event", matches);
                                    });
                                 
                                    //load the initial screen
                                    homeScreen(matches);



});

APP.vent.on("futureGames:event", function(matches){
console.log(matches.toJSON())
});

APP.vent.on("homeBtn:event", function(matches){
  APP.vent.trigger("matchesCollectionLoaded:event", matches);
});


//end events


var homeScreen = function(matches){
  $("#allMatches").html(matchesModelView.render().el);
}




}); //end doc ready