diff --git a/app/assets/javascripts/spine/mobile/panel.js b/app/assets/javascripts/spine/mobile/panel.js
new file mode 100644
index 0000000..c44067a
--- /dev/null
+++ b/app/assets/javascripts/spine/mobile/panel.js
@@ -0,0 +1,132 @@
+(function() {
+ var $, Gfx, Panel, Stage;
+ var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) {
+ for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }
+ function ctor() { this.constructor = child; }
+ ctor.prototype = parent.prototype;
+ child.prototype = new ctor;
+ child.__super__ = parent.prototype;
+ return child;
+ }, __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
+ $ = Spine.$;
+ Gfx = require('gfx');
+ Stage = require('./stage');
+ Panel = (function() {
+ __extends(Panel, Stage);
+ Panel.prototype.title = false;
+ Panel.prototype.viewport = false;
+ function Panel() {
+ var _ref, _ref2;
+ Panel.__super__.constructor.apply(this, arguments);
+ this.el.removeClass('stage').addClass('panel');
+ this.header.append($('
'));
+ if (this.title) {
+ this.setTitle(this.title);
+ }
+ if ((_ref = this.stage) == null) {
+ this.stage = Stage.globalStage();
+ }
+ if ((_ref2 = this.stage) != null) {
+ _ref2.add(this);
+ }
+ }
+ Panel.prototype.setTitle = function(title) {
+ if (title == null) {
+ title = '';
+ }
+ return this.header.find('h2:first').html(title);
+ };
+ Panel.prototype.addButton = function(text, callback) {
+ var button;
+ if (typeof callback === 'string') {
+ callback = this[callback];
+ }
+ button = $('').text(text);
+ button.tap(this.proxy(callback));
+ this.header.append(button);
+ return button;
+ };
+ Panel.prototype.activate = function(params) {
+ var effect;
+ if (params == null) {
+ params = {};
+ }
+ effect = params.transition || params.trans;
+ if (effect) {
+ return this.effects[effect].apply(this);
+ } else {
+ this.content.add(this.header).show();
+ return this.el.addClass('active');
+ }
+ };
+ Panel.prototype.deactivate = function(params) {
+ var effect;
+ if (params == null) {
+ params = {};
+ }
+ if (!this.isActive()) {
+ return;
+ }
+ effect = params.transition || params.trans;
+ if (effect) {
+ return this.reverseEffects[effect].apply(this);
+ } else {
+ return this.el.removeClass('active');
+ }
+ };
+ Panel.prototype.effects = {
+ left: function() {
+ this.el.addClass('active');
+ this.content.gfxSlideIn(this.effectOptions({
+ direction: 'left'
+ }));
+ return this.header.gfxSlideIn(this.effectOptions({
+ direction: 'left',
+ fade: true,
+ distance: 50
+ }));
+ },
+ right: function() {
+ this.el.addClass('active');
+ this.content.gfxSlideIn(this.effectOptions({
+ direction: 'right'
+ }));
+ return this.header.gfxSlideIn(this.effectOptions({
+ direction: 'right',
+ fade: true,
+ distance: 50
+ }));
+ }
+ };
+ Panel.prototype.reverseEffects = {
+ left: function() {
+ this.content.gfxSlideOut(this.effectOptions({
+ direction: 'right'
+ }));
+ this.header.gfxSlideOut(this.effectOptions({
+ direction: 'right',
+ fade: true,
+ distance: 50
+ }));
+ return this.content.queueNext(__bind(function() {
+ return this.el.removeClass('active');
+ }, this));
+ },
+ right: function() {
+ this.content.gfxSlideOut(this.effectOptions({
+ direction: 'left'
+ }));
+ this.header.gfxSlideOut(this.effectOptions({
+ direction: 'left',
+ fade: true,
+ distance: 50
+ }));
+ return this.content.queueNext(__bind(function() {
+ return this.el.removeClass('active');
+ }, this));
+ }
+ };
+ return Panel;
+ })();
+ (typeof module !== "undefined" && module !== null ? module.exports = Panel : void 0) || (this.Panel = Panel);
+}).call(this);
diff --git a/app/assets/javascripts/spine/mobile/stage.js b/app/assets/javascripts/spine/mobile/stage.js
new file mode 100644
index 0000000..cae0f4f
--- /dev/null
+++ b/app/assets/javascripts/spine/mobile/stage.js
@@ -0,0 +1,146 @@
+(function() {
+ var $, Spine, Stage, globalManager;
+ var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) {
+ for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }
+ function ctor() { this.constructor = child; }
+ ctor.prototype = parent.prototype;
+ child.prototype = new ctor;
+ child.__super__ = parent.prototype;
+ return child;
+ }, __slice = Array.prototype.slice, __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
+ Spine = require('spine');
+ $ = Spine.$;
+ globalManager = new Spine.Manager;
+ Stage = (function() {
+ __extends(Stage, Spine.Controller);
+ Stage.globalManager = function() {
+ return globalManager;
+ };
+ Stage.globalStage = function() {
+ return this.globalManager().controllers[0];
+ };
+ Stage.prototype.effectDefaults = {
+ duration: 450,
+ easing: 'cubic-bezier(.25, .1, .25, 1)'
+ };
+ Stage.prototype.effectOptions = function(options) {
+ if (options == null) {
+ options = {};
+ }
+ return $.extend({}, this.effectDefaults, options);
+ };
+ Stage.prototype.viewport = true;
+ function Stage() {
+ Stage.__super__.constructor.apply(this, arguments);
+ this.el.addClass('stage');
+ this.header = $('');
+ this.content = $('');
+ this.footer = $('');
+ if (this.viewport) {
+ this.content.addClass('viewport');
+ }
+ this.el.append(this.header, this.content, this.footer);
+ if (this.global) {
+ globalManager.add(this);
+ }
+ }
+ Stage.prototype.append = function() {
+ var e, elements, _ref;
+ elements = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
+ elements = (function() {
+ var _i, _len, _results;
+ _results = [];
+ for (_i = 0, _len = elements.length; _i < _len; _i++) {
+ e = elements[_i];
+ _results.push(e.el || e);
+ }
+ return _results;
+ })();
+ return (_ref = this.content).append.apply(_ref, elements);
+ };
+ Stage.prototype.html = function() {
+ this.content.html.apply(this.content, arguments);
+ this.refreshElements();
+ return this.content;
+ };
+ Stage.prototype.add = function() {
+ var panels, _ref;
+ panels = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
+ this.manager || (this.manager = new Spine.Manager);
+ (_ref = this.manager).add.apply(_ref, panels);
+ return this.append.apply(this, panels);
+ };
+ Stage.prototype.activate = function(params) {
+ var effect;
+ if (params == null) {
+ params = {};
+ }
+ effect = params.transition || params.trans;
+ if (effect) {
+ return this.effects[effect].apply(this);
+ } else {
+ return this.el.addClass('active');
+ }
+ };
+ Stage.prototype.deactivate = function(params) {
+ var effect;
+ if (params == null) {
+ params = {};
+ }
+ if (!this.isActive()) {
+ return;
+ }
+ effect = params.transition || params.trans;
+ if (effect) {
+ return this.reverseEffects[effect].apply(this);
+ } else {
+ return this.el.removeClass('active');
+ }
+ };
+ Stage.prototype.isActive = function() {
+ return this.el.hasClass('active');
+ };
+ Stage.prototype.effects = {
+ left: function() {
+ this.el.addClass('active');
+ return this.el.gfxSlideIn(this.effectOptions({
+ direction: 'left'
+ }));
+ },
+ right: function() {
+ this.el.addClass('active');
+ return this.el.gfxSlideIn(this.effectOptions({
+ direction: 'right'
+ }));
+ }
+ };
+ Stage.prototype.reverseEffects = {
+ left: function() {
+ this.el.gfxSlideOut(this.effectOptions({
+ direction: 'right'
+ }));
+ return this.el.queueNext(__bind(function() {
+ return this.el.removeClass('active');
+ }, this));
+ },
+ right: function() {
+ this.el.gfxSlideOut(this.effectOptions({
+ direction: 'left'
+ }));
+ return this.el.queueNext(__bind(function() {
+ return this.el.removeClass('active');
+ }, this));
+ }
+ };
+ return Stage;
+ })();
+ Stage.Global = (function() {
+ __extends(Global, Stage);
+ function Global() {
+ Global.__super__.constructor.apply(this, arguments);
+ }
+ Global.prototype.global = true;
+ return Global;
+ })();
+ (typeof module !== "undefined" && module !== null ? module.exports = Stage : void 0) || (this.Stage = Stage);
+}).call(this);
diff --git a/app/assets/javascripts/spine/mobile/touch.js b/app/assets/javascripts/spine/mobile/touch.js
new file mode 100644
index 0000000..543784f
--- /dev/null
+++ b/app/assets/javascripts/spine/mobile/touch.js
@@ -0,0 +1,79 @@
+(function() {
+ var $, m, parentIfText, swipeDirection, touch, types, _fn, _i, _len;
+ $ = require('spine').$;
+ $.support.touch = 'ontouchstart' in window;
+ touch = {};
+ parentIfText = function(node) {
+ if ('tagName' in node) {
+ return node;
+ } else {
+ return node.parentNode;
+ }
+ };
+ swipeDirection = function(x1, x2, y1, y2) {
+ var xDelta, yDelta;
+ xDelta = Math.abs(x1 - x2);
+ yDelta = Math.abs(y1 - y2);
+ if (xDelta >= yDelta) {
+ if (x1 - x2 > 0) {
+ return 'Left';
+ } else {
+ return 'Right';
+ }
+ } else {
+ if (y1 - y2 > 0) {
+ return 'Up';
+ } else {
+ return 'Down';
+ }
+ }
+ };
+ $(function() {
+ return $('body').bind('touchstart', function(e) {
+ var delta, now;
+ e = e.originalEvent;
+ now = Date.now();
+ delta = now - (touch.last || now);
+ touch.target = parentIfText(e.touches[0].target);
+ touch.x1 = e.touches[0].pageX;
+ touch.y1 = e.touches[0].pageY;
+ return touch.last = now;
+ }).bind('touchmove', function(e) {
+ e = e.originalEvent;
+ touch.x2 = e.touches[0].pageX;
+ return touch.y2 = e.touches[0].pageY;
+ }).bind('touchend', function(e) {
+ e = e.originalEvent;
+ if (touch.x2 > 0 || touch.y2 > 0) {
+ (Math.abs(touch.x1 - touch.x2) > 30 || Math.abs(touch.y1 - touch.y2) > 30) && $(touch.target).trigger('swipe') && $(touch.target).trigger('swipe' + (swipeDirection(touch.x1, touch.x2, touch.y1, touch.y2)));
+ return touch.x1 = touch.x2 = touch.y1 = touch.y2 = touch.last = 0;
+ } else if ('last' in touch) {
+ $(touch.target).trigger('tap');
+ return touch = {};
+ }
+ }).bind('touchcancel', function(e) {
+ return touch = {};
+ });
+ });
+ if ($.support.touch) {
+ $('body').bind('click', function(e) {
+ return e.preventDefault();
+ });
+ } else {
+ $(function() {
+ return $('body').bind('click', function(e) {
+ return $(e.target).trigger('tap');
+ });
+ });
+ }
+ types = ['swipe', 'swipeLeft', 'swipeRight', 'swipeUp', 'swipeDown', 'tap'];
+ _fn = function(m) {
+ return $.fn[m] = function(callback) {
+ return this.bind(m, callback);
+ };
+ };
+ for (_i = 0, _len = types.length; _i < _len; _i++) {
+ m = types[_i];
+ _fn(m);
+ }
+}).call(this);