Skip to content

Instantly share code, notes, and snippets.

@kixxauth
Created December 17, 2014 17:09
Show Gist options
  • Save kixxauth/7a32c36b68fe5db4fc26 to your computer and use it in GitHub Desktop.
Save kixxauth/7a32c36b68fe5db4fc26 to your computer and use it in GitHub Desktop.
Code examples from Backbone and Marionette on the Xbox One
// ## Setup the application:
//
// application.js
var BackboneApp, BA;
BackboneApp = BA = (function (Backbone, Marionette) {
var Application = Marionette.Application.extend({
// ... MOAR code ...
});
return new Application();
}(window.Backbone, window.Marionette));
// ## Use events to decauple components:
//
// default.js
(function (App) {
// Application
App.reqres.setHandler('applicationData:topic', App.Entities.getTopic);
App.reqres.setHandler('applicationData:topic:related:promise', App.Entities.getRelatedTopic);
App.reqres.setHandler('applicationData:topics:filter', App.Entities.topicsFilter);
App.reqres.setHandler('applicationData:topics:tagged', App.Entities.taggedTopics);
App.reqres.setHandler('applicationData:topics:games', App.Entities.gameTopics);
App.reqres.setHandler('applicationData:topics:officials', App.Entities.officialsTopics);
App.reqres.setHandler('applicationData:topic:focused', App.Entities.focusedTopic);
App.reqres.setHandler('applicationData:init:promise', App.Entities.initData);
// Matches
App.reqres.setHandler('matches:fetch', App.DataService.Matches.fetch);
App.reqres.setHandler('offline_matches:fetch', App.DataService.OfflineMatches.fetch);
}(BackboneApp);
// ## Commit to promises at the start
//
// backbone/ajax.js
BackboneApp.module('Ajax', function (Ajax, App, Backbone) {
Backbone.ajax = function (args) {
return new WinJS.Promise(function (resolve, reject) {
function onsuccess() {
// ... handle success ...
resolve(stuff);
}
function onerror() {
// ... handle error ...
reject(err);
}
Backbone.$
.ajax(args)
.then(onsuccess, onerror);
});
};
});
// components/data_service_matches.js
BackboneApp.module('DataService.Matches', function (Service, App, Backbone) {
var _collection = null,
_initial_promise = null;
_.extend(Service, {
fetch: function fetch(opts) {
if (opts.cache && _initial_promise) {
return _initial_promise;
} else {
return Service.getInitial();
}
},
getInitial: function getInitial() {
if (!_collection) {
_collection = new App.Entities.Matches();
}
_initial_promise = new WinJS.Promise(function (resolve, reject) {
fetchDataFromSuperSecretXboxLiveService().then(function (data) {
_collection.set(data);
return _collection;
});
});
return _initial_promise;
}
});
});
// Promises allow us to do:
Component = App.Components.Base.extend({
activate: function activate() {
this.getApplicationData()
.then(this.withApplicationData.bind(this))
.then(Data.getUserMatches({cache: true}))
.then(this.withMatches.bind(this))
.then(this.withDependencies.bind(this))
.then(null, this.onActivationError.bind(this));
},
getApplicationData: function getApplicationData() {
return WinJS.Promise.join({
appdata: App.DataService.Application.getApplicationData(),
user: App.DataService.User.getUser()
});
},
withApplicationData: function withApplicationData(res) {
this.user = res.user;
},
getUserMatches: function getUserMatches(opts) {
return BackboneApp.DataService.Matches.fetch(opts);
},
withMatches: function withMatches(matches) {
this.matches = matches;
},
withDependencies: function withDependencies() {},
onActivationError: function onActivationError(err) {}
});
// ## Ugly hacks for Marionette Regions to work with Xbox page change
//
Regions.Base = Marionette.Region.extend({
getEl: function getEl(el) {
if (_.isFunction(el)) { el = this.el = el.call(this); }
if (_.isObject(el)) { return Backbone.$(el); }
var $el, parentEl = this.getOption('parentEl');
el = convertIdSelector(el);
if (_.isFunction(parentEl)) { parentEl = parentEl(); }
if (parentEl) {
$el = parentEl.find(el);
if ($el.length) {
return $el;
}
}
return Backbone.$(el);
}
});
var selectorRx = /^#/;
function convertIdSelector(selector) {
if (_.isString(selector) && selectorRx.test(selector)) {
return '[id="'+ selector.replace(selectorRx, '') +'"]';
}
return selector;
}
// Effectively:
region.el = region.parentEl.find('[id="my-id"]')[1];
// ## Create your own classes
//
BackboneApp.module('DataService', function (Service, App, Backbone, Marionette) {
Service.Socket = Marionette.Object.extend({
initialize: function initialize() {
},
connect: function connect(url) {
},
close: function close() {
},
onRemoteEvent: function onRemoteEvent(event, handler) {
},
triggerRemoteEvent: function triggerRemoteEvent(event, args) {
},
isReady: function isReady() {
}
});
});
// ## Use Super Classes
//
BackboneApp.module('SomeComponent', function (Component, App, Backbone) {
// Create more specific classes from the base classes in here:
Component.Topic = App.Entities.Model.extend({
});
Component.Topics = App.Entities.Collection.extend({
});
Component.LayoutView = App.Views.LayoutView.extend({
});
});
// ## Setup your own super classes:
//
// backbone/components.js
BackboneApp.module('Components', function (Components, App, Backbone, Marionette) {
Components.Base = Marionette.Object.extend({
// ... MOAR code ...
});
});
// backbone/controllers.js
BackboneApp.module('Controllers', function (Controllers, App, Backbone, Marionette) {
Controllers.Base = Marionette.Controller.extend({
// ... MOAR code ...
});
});
// backbone/entities.js
BackboneApp.module('Entities', function(Entities, App, Backbone, Marionette) {
Entities.Model = Backbone.Model.extend({
// ... MOAR code ...
});
Entities.Collection = Backbone.Collection.extend({
// ... MOAR code ...
});
});
// backbone/regions.js
BackboneApp.module('Regions', function (Regions, App, Backbone, Marionette) {
Marionette.Region._buildRegionFromObject = function () {
// ... MOAR code ...
};
Regions.Base = Marionette.Region.extend({
// ... MOAR code ...
});
});
// backbone/views.js
BackboneApp.module('Views', function(Views, App, Backbone, Marionette) {
_.extend(Marionette.View.prototype, {
remove: function remove() {
if (!this.getOption('preserveElement')) {
this.$el.remove();
}
this.stopListening();
return this;
},
});
Views.ItemView = Marionette.ItemView.extend({
});
Views.CollectionView = Marionette.CollectionView.extend({
});
Views.CompositeView = Marionette.CompositeView.extend({
});
Views.LayoutView = Marionette.LayoutView.extend({
});
});
// ## Some ugly hacks used for views on Xbox:
//
_.extend(Marionette.ItemView.prototype, {
_renderTemplate: function _renderTemplate() {
if (_.isFunction(this.activate)) {
this.activate();
}
return this;
}
});
// Allows Us to do:
Views.MediaTile = Views.ItemView.extend({
activate: function activate() {
this.tile = this.buildTile({
contentId: this.model.id,
title: this.model.title,
image: this.model.image_url
})
this.tile.addEventListener('invoked', function () {
this.trigger('clicked', this);
}.bind(this));
},
buildTile: function buildTile(spec) {
return new XboxJS.UI.MediaTile(this.el, {
contentId: spec.content_id,
title: spec.title,
image: spec.image
});
}
});
(function() {
var
XboxUser = Windows.Xbox.System.User,
XboxUI = Windows.Xbox.UI,
SystemUI = XboxUI.SystemUI,
Services = Microsoft.Xbox.Services;
WinJS.Namespace.define('Platform.User', {
enumerateUsers: enumerateUsers,
getProfile: getProfile,
getContextUser: getContextUser
});
}());
// Allows us to do:
Platform.User.enumerateUsers();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment