sports_db 0.0.3 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/app/assets/javascripts/clients/android/client.js +53 -0
- data/app/assets/javascripts/clients/ios/client.js +58 -0
- data/app/assets/javascripts/core/Application.js +173 -0
- data/app/assets/javascripts/core/BaseView.js +117 -0
- data/app/assets/javascripts/core/History.js +45 -0
- data/app/assets/javascripts/core/Mock.js +90 -0
- data/app/assets/javascripts/core/Timer.js +18 -0
- data/app/assets/javascripts/core/View.js +56 -0
- data/app/assets/javascripts/core/utilities.js +81 -0
- data/app/assets/javascripts/libs/SimpleInheritance.js +53 -0
- data/app/assets/javascripts/libs/microjungle.zepto.js +45 -0
- data/app/assets/javascripts/libs/zepto-v1.0rc1/ajax.js +279 -0
- data/app/assets/javascripts/libs/zepto-v1.0rc1/assets.js +21 -0
- data/app/assets/javascripts/libs/zepto-v1.0rc1/data.js +66 -0
- data/app/assets/javascripts/libs/zepto-v1.0rc1/detect.js +40 -0
- data/app/assets/javascripts/libs/zepto-v1.0rc1/event.js +224 -0
- data/app/assets/javascripts/libs/zepto-v1.0rc1/form.js +40 -0
- data/app/assets/javascripts/libs/zepto-v1.0rc1/fx.js +91 -0
- data/app/assets/javascripts/libs/zepto-v1.0rc1/fx_methods.js +72 -0
- data/app/assets/javascripts/libs/zepto-v1.0rc1/gesture.js +35 -0
- data/app/assets/javascripts/libs/zepto-v1.0rc1/polyfill.js +36 -0
- data/app/assets/javascripts/libs/zepto-v1.0rc1/selector.js +70 -0
- data/app/assets/javascripts/libs/zepto-v1.0rc1/stack.js +22 -0
- data/app/assets/javascripts/libs/zepto-v1.0rc1/touch.js +85 -0
- data/app/assets/javascripts/libs/zepto-v1.0rc1/zepto.js +591 -0
- data/app/assets/javascripts/libs/zepto_0.8.js +1213 -0
- data/app/assets/javascripts/plugins/assert.js +11 -0
- data/app/assets/javascripts/plugins/calnav.js +18 -0
- data/app/assets/javascripts/plugins/detect.js +16 -0
- data/app/assets/javascripts/plugins/filterable.js +12 -0
- data/app/assets/javascripts/plugins/flash.js +15 -0
- data/app/assets/javascripts/plugins/jquery.zumobi-0.2.js +57 -0
- data/app/assets/javascripts/plugins/loading.js +47 -0
- data/app/assets/javascripts/plugins/params.js +27 -0
- data/app/assets/javascripts/plugins/resizeable.js +40 -0
- data/app/assets/stylesheets/_base.css.scss +42 -0
- data/app/assets/stylesheets/_filterable.css.scss +19 -0
- data/app/assets/stylesheets/_flash.css.scss +9 -0
- data/app/assets/stylesheets/_loading.css.scss +28 -0
- data/app/assets/stylesheets/_play.css.scss +38 -0
- data/app/assets/stylesheets/_reset.css.scss +33 -0
- data/app/assets/stylesheets/_table_base.scss +121 -0
- data/app/assets/stylesheets/mock.css.scss +52 -0
- data/app/controllers/application_controller.rb +39 -0
- data/app/views/application/load.html.erb +1 -0
- data/app/views/layouts/application.html.erb +27 -0
- data/lib/sports_db/version.rb +1 -1
- metadata +90 -5
@@ -0,0 +1,53 @@
|
|
1
|
+
if ($.client.android) {
|
2
|
+
console.log('=> Using AndroidClient.js');
|
3
|
+
|
4
|
+
// This should be in a mock file...
|
5
|
+
if (!window.ClientBridge) {
|
6
|
+
window.ClientBridge = {
|
7
|
+
notify: function(obj) {
|
8
|
+
window.console.debug(obj);
|
9
|
+
}
|
10
|
+
};
|
11
|
+
}
|
12
|
+
|
13
|
+
var Client = Class.extend({
|
14
|
+
initialize: function() {
|
15
|
+
|
16
|
+
},
|
17
|
+
/**
|
18
|
+
* Called by the web application to send values to the client.
|
19
|
+
*
|
20
|
+
* @param {Object} obj - a set of key/value parameters to send to client
|
21
|
+
*/
|
22
|
+
notify: function(obj) {
|
23
|
+
var arr = [];
|
24
|
+
for (var prop in obj) {
|
25
|
+
arr.push(prop +'='+ encodeURIComponent(obj[prop]));
|
26
|
+
}
|
27
|
+
ClientBridge.notify( arr.join('&') );
|
28
|
+
},
|
29
|
+
|
30
|
+
/**
|
31
|
+
* Called by the client to set a value or trigger an action in the web page.
|
32
|
+
*
|
33
|
+
* @param {String} name
|
34
|
+
* @param {Object} value (optional)
|
35
|
+
*/
|
36
|
+
callback: function(name, value) {
|
37
|
+
Application.onClientCallback(name, value);
|
38
|
+
}
|
39
|
+
});
|
40
|
+
|
41
|
+
// Singleton
|
42
|
+
Client = new Client();
|
43
|
+
|
44
|
+
// Fix console as it doesn't appear to exist in Android WebView, and we frequently leave these statements in our code
|
45
|
+
if (!window.console) {
|
46
|
+
window.console = {};
|
47
|
+
var f = function() {};
|
48
|
+
["debug", "info", "warn", "error", "assert", "dir", "dirxml", "trace", "group", "groupCollapsed",
|
49
|
+
"groupEnd", "time", "timeEnd", "profile", "profileEnd", "count"].forEach(function(func) {
|
50
|
+
window.console[func] = f;
|
51
|
+
});
|
52
|
+
}
|
53
|
+
}
|
@@ -0,0 +1,58 @@
|
|
1
|
+
if ($.client.ios) {
|
2
|
+
console.log('=> Using iOSClient.js');
|
3
|
+
|
4
|
+
var Client = Class.extend({
|
5
|
+
// Called by the web application to send values to the client.
|
6
|
+
//
|
7
|
+
// @param {Object} obj - a set of key/value parameters to send to client
|
8
|
+
notify: function(obj) {
|
9
|
+
if (top.location === self.location) {
|
10
|
+
this._createUrlForClientInterception("client_notify", obj);
|
11
|
+
}
|
12
|
+
},
|
13
|
+
// Called by the client to set a value or trigger an action in the web page.
|
14
|
+
//
|
15
|
+
// @param {String} name
|
16
|
+
// @param {Object} value (optional)
|
17
|
+
callback: function(name, value) {
|
18
|
+
Application.onClientCallback(name, value);
|
19
|
+
},
|
20
|
+
_createUrlForClientInterception: function(prefix, obj) {
|
21
|
+
this._initClientTransportIfNecessary(prefix);
|
22
|
+
for (var prop in obj) {
|
23
|
+
if (typeof obj[prop] !== 'function') {
|
24
|
+
var input = document.createElement("input");
|
25
|
+
input.type = "hidden";
|
26
|
+
input.name = prop;
|
27
|
+
// these do not need to be encoded, because the form does this for us.
|
28
|
+
input.value = obj[prop];
|
29
|
+
this.form.appendChild(input);
|
30
|
+
}
|
31
|
+
}
|
32
|
+
// prevent embedded iframe from being source of further events.
|
33
|
+
if (top.location === self.location) {
|
34
|
+
this.form.submit();
|
35
|
+
}
|
36
|
+
},
|
37
|
+
_initClientTransportIfNecessary: function(prefix) {
|
38
|
+
if (this.iframe === null || this.iframe === undefined) {
|
39
|
+
this.iframe = document.createElement("iframe");
|
40
|
+
this.iframe.name = "postit";
|
41
|
+
this.iframe.setAttribute("style", "position:absolute; left:-1000px; top:-100px;");
|
42
|
+
this.iframe.width = this.iframe.height = 10;
|
43
|
+
document.body.appendChild(this.iframe);
|
44
|
+
|
45
|
+
this.form = document.createElement("form");
|
46
|
+
this.form.target = "postit";
|
47
|
+
this.form.style.visibility = "hidden";
|
48
|
+
this.form.style.position = "absolute";
|
49
|
+
document.body.appendChild(this.form);
|
50
|
+
}
|
51
|
+
this.form.action = prefix;
|
52
|
+
this.form.innerHTML = "";
|
53
|
+
}
|
54
|
+
});
|
55
|
+
|
56
|
+
// Singleton
|
57
|
+
Client = new Client();
|
58
|
+
}
|
@@ -0,0 +1,173 @@
|
|
1
|
+
var Application = Class.extend({
|
2
|
+
initialize: function() {
|
3
|
+
this.app_is_initializing = true;
|
4
|
+
this.views = {};
|
5
|
+
this.params = {};
|
6
|
+
this.cache = {};
|
7
|
+
this.currentView = null;
|
8
|
+
this.clientCallbackHandlers = [];
|
9
|
+
this.params = {};
|
10
|
+
|
11
|
+
// Get hash params
|
12
|
+
if (window.location.hash) {
|
13
|
+
this.params = $.hashStrToObj();
|
14
|
+
}
|
15
|
+
|
16
|
+
// I'm not reallys ure we want to store these together, but whatever (For now)
|
17
|
+
this.params = $.extend(window.CONFIG, this.params);
|
18
|
+
|
19
|
+
// Start timer for game updates
|
20
|
+
// TODO only run this on game views
|
21
|
+
this.timer = new Timer($.proxy(this._fireTimerEvent, this), this.params.GAME_UPDATE_FREQUENCY);
|
22
|
+
this.timer.start();
|
23
|
+
},
|
24
|
+
// Fire a timer event
|
25
|
+
_fireTimerEvent: function() {
|
26
|
+
$(document.body).trigger("timerReachInterval", false, false);
|
27
|
+
},
|
28
|
+
// Call the view if the method exists
|
29
|
+
_onTimerReachedInterval: function() {
|
30
|
+
var view = this.currentView;
|
31
|
+
if (view && view._onTimerReachedInterval) {
|
32
|
+
view._onTimerReachedInterval.call(view);
|
33
|
+
}
|
34
|
+
},
|
35
|
+
// Register a view constructor under a specific name. If a link in the application has
|
36
|
+
// a parameter named "view" that points to a registered view name, then the `Application`
|
37
|
+
// will load that view. Optionally, you can pass in parameters, and these will be merged
|
38
|
+
// with any other parameters in the link that triggers view loading (parameters in the
|
39
|
+
// link override parameters in the registration binding). This allows you to bind the
|
40
|
+
// same view under different names with different parameters in order to parameterize
|
41
|
+
// its behavior.
|
42
|
+
//
|
43
|
+
// @param {Object} name
|
44
|
+
// @param {Object} constructor
|
45
|
+
// @param {Object} params (optional)
|
46
|
+
registerView: function(name, constructor, params) {
|
47
|
+
this.views[name] = { constructor: constructor, params: (params || {}) };
|
48
|
+
},
|
49
|
+
// Stash a view, i.e. change the url to something meaningful, but do not show the
|
50
|
+
// view based on this URL change. This is needed in cases where the device goes to
|
51
|
+
// sleep, and then reloads upon awakening.
|
52
|
+
stashView: function(params) {
|
53
|
+
var local = {};
|
54
|
+
local.view = params.view;
|
55
|
+
if (params.filter) { local.filter = params.filter; }
|
56
|
+
if (params.key) { local.key = params.key; }
|
57
|
+
local.stash = true;
|
58
|
+
var url = "#" + $.objToQueryStr(local);
|
59
|
+
|
60
|
+
document.location = url;
|
61
|
+
},
|
62
|
+
// Show a view based on the supplied parameters. The only required parameter is "view"
|
63
|
+
// which must reference a valid view name.
|
64
|
+
//
|
65
|
+
// @param {Object} params
|
66
|
+
showView: function(params) {
|
67
|
+
$.assert(params.view, "No view specified (use #view=<viewName>)", "Error: no view specified.");
|
68
|
+
var binding = this.views[params.view];
|
69
|
+
|
70
|
+
$.assert(binding, params.view + " is not a registered view name. Did you add it to views.js?", "Error: not a registered view.");
|
71
|
+
|
72
|
+
// Merge binding parameters (from views.js) into any parameters that were supplied in the URL
|
73
|
+
for (var prop in binding.params) {
|
74
|
+
if (typeof params[prop] === 'undefined') {
|
75
|
+
params[prop] = binding.params[prop];
|
76
|
+
}
|
77
|
+
}
|
78
|
+
var view = new binding.constructor(params);
|
79
|
+
$.assert(view.create, params.view + " doesn't have a create method and is not a valid view", "Error: not a valid view.");
|
80
|
+
|
81
|
+
view.create();
|
82
|
+
},
|
83
|
+
// When the view is done initializing, it must call this method.
|
84
|
+
appendView: function(view) {
|
85
|
+
view.beforeViewAppended(view.params);
|
86
|
+
view.buffer.html('empty');
|
87
|
+
|
88
|
+
// if we have a reference to the previous view, remove() it
|
89
|
+
if (this.currentView && this.currentView.element) {
|
90
|
+
$(this.currentView.element).remove();
|
91
|
+
}
|
92
|
+
|
93
|
+
// re-assign this.curentView to the new view, and add it to the
|
94
|
+
// Application.cache
|
95
|
+
this.currentView = this.cache[History.currentHash()] = view;
|
96
|
+
|
97
|
+
document.body.appendChild(view.element);
|
98
|
+
|
99
|
+
if (view.params.scrollY) {
|
100
|
+
window.scrollTo(0,view.params.scrollY);
|
101
|
+
this.params.scrollY = 0;
|
102
|
+
} else {
|
103
|
+
window.scrollTo(0,0);
|
104
|
+
}
|
105
|
+
$.alignLoader();
|
106
|
+
|
107
|
+
view.afterViewAppended(view.params);
|
108
|
+
|
109
|
+
$(view.element).addClass('cached');
|
110
|
+
if (!view.params.skip_metrics === true) this.sendMetrics();
|
111
|
+
},
|
112
|
+
sendMetrics: function() {
|
113
|
+
var view = Application.currentView;
|
114
|
+
Client.notify({
|
115
|
+
"metric": view.getMetric(),
|
116
|
+
"title": view.getTitle(),
|
117
|
+
"buttons": view.getButtons(),
|
118
|
+
"action": view.getAction(),
|
119
|
+
"filter": view.getFilter(),
|
120
|
+
"section": view.getSection()
|
121
|
+
});
|
122
|
+
},
|
123
|
+
// The web application is receiving a callback from the client to set a value or execute some
|
124
|
+
// behavior. If the view has an `onClientCallback` method, this will be executed first. It can
|
125
|
+
// cancel any further event handling by returning `true`. Otherwise, the application sends the
|
126
|
+
// event to all of the `clientCallbackHandlers` that are registered with the application, in the
|
127
|
+
// order they were registered.
|
128
|
+
//
|
129
|
+
// @param {String} name
|
130
|
+
// @param {Object} value
|
131
|
+
onClientCallback: function(name, value) {
|
132
|
+
var handled = false;
|
133
|
+
var view = this.currentView;
|
134
|
+
if (view && view.onClientCallback) {
|
135
|
+
handled = view.onClientCallback.call(view, name, value);
|
136
|
+
}
|
137
|
+
if (!handled) {
|
138
|
+
this.clientCallbackHandlers.forEach(function(handler) {
|
139
|
+
handler.call(this, name, value);
|
140
|
+
}, this);
|
141
|
+
}
|
142
|
+
},
|
143
|
+
// load a view from cache or the server when we get a hashchange event
|
144
|
+
_onHashChange: function(event, data) {
|
145
|
+
// If the app is not initializing, and the view is stashed, do not do anything
|
146
|
+
if (!this.app_is_initializing && data.stash) {
|
147
|
+
console.log('=> App is not initializing & a view is stashed. RETURN');
|
148
|
+
return;
|
149
|
+
}
|
150
|
+
|
151
|
+
$.assert(data.view, "No view specified (use #view=<viewName>)", "Error: no view specified.");
|
152
|
+
|
153
|
+
var view = this.cache[History.currentHash()];
|
154
|
+
view ? this.appendView(view) : this.showView(data);
|
155
|
+
|
156
|
+
this.app_is_initializing = false;
|
157
|
+
},
|
158
|
+
// Initializes application functionality on page load, and kicks off loading the view.
|
159
|
+
//
|
160
|
+
// @private
|
161
|
+
_onReady: function() {
|
162
|
+
$(document.body)
|
163
|
+
.on("hashchange", $.proxy(Application._onHashChange, this))
|
164
|
+
.on("timerReachInterval", $.proxy(Application._onTimerReachedInterval, this));
|
165
|
+
}
|
166
|
+
});
|
167
|
+
|
168
|
+
// Singleton.
|
169
|
+
Application = new Application();
|
170
|
+
|
171
|
+
Zepto(function($) {
|
172
|
+
Application._onReady();
|
173
|
+
});
|
@@ -0,0 +1,117 @@
|
|
1
|
+
// A basic view implementation that expects an `URL` to be passed as one of the parameters
|
2
|
+
// to the view; it will format that `URL` using any other parameters, and use it to retrieve
|
3
|
+
// an `HTML` fragment from the server. This is only one of many strategies that could be
|
4
|
+
// followed to create views, of course. It also assumes that the parameters object will
|
5
|
+
// get a title property.
|
6
|
+
var BaseView = View.extend({
|
7
|
+
// Subclasses must ensure there is an url property to the parameter object passed
|
8
|
+
// into this superconstructor, i.e.:
|
9
|
+
//
|
10
|
+
// this._super(params)
|
11
|
+
//
|
12
|
+
// Any parameters passed in to the view constructor will be substituted
|
13
|
+
// into the URL string using the String format method (see utilities.js).
|
14
|
+
//
|
15
|
+
// @param {Object} params
|
16
|
+
initialize: function(params) {
|
17
|
+
this.url = this.getUrl(params);
|
18
|
+
this.params = params;
|
19
|
+
this.buffer = Application.params.BUFFER_EL;
|
20
|
+
},
|
21
|
+
getUrl: function(params) {
|
22
|
+
if (params.url) {
|
23
|
+
return params.url.format(params);
|
24
|
+
} else {
|
25
|
+
return "/" + Application.params.APP_NAME + "/" + params.view;
|
26
|
+
}
|
27
|
+
},
|
28
|
+
getTitle: function() {
|
29
|
+
// The title varies on the Team View between Android and iOS.
|
30
|
+
// cstuart 2011-08-29
|
31
|
+
if ($.client.ios) {
|
32
|
+
this.params.title = this.params.ios_title || this.params.title;
|
33
|
+
}
|
34
|
+
return this.params.title || this.params.view.capitalize();
|
35
|
+
},
|
36
|
+
getMetric: function() {
|
37
|
+
return this.params.metric || "/" + this.params.view.capitalize();
|
38
|
+
},
|
39
|
+
getButtons: function() {
|
40
|
+
return this.params.buttons || "Back:";
|
41
|
+
},
|
42
|
+
getAction: function() {
|
43
|
+
return this.params.action || "<None>";
|
44
|
+
},
|
45
|
+
getFilter: function() {
|
46
|
+
return this.params.filter || "<None>";
|
47
|
+
},
|
48
|
+
getSection: function() {
|
49
|
+
return this.params.view;
|
50
|
+
},
|
51
|
+
// Loads the content of the view from the server (the content should be wrapped by a `div`).
|
52
|
+
// The content is inserted into the page.
|
53
|
+
create: function() {
|
54
|
+
var view = this;
|
55
|
+
|
56
|
+
// This is a hack. The TSN keys include periods that confuse the Rails page caching system. Convert
|
57
|
+
// here to underscores, and back to periods again on the server using a filter.
|
58
|
+
view.url = view.url.replace(/\./g,"_");
|
59
|
+
|
60
|
+
function onError() {
|
61
|
+
var params = {};
|
62
|
+
// The old currentView won't exist in the case of a 404 or
|
63
|
+
// other server error.
|
64
|
+
if (Application.currentView && Application.currentView.params) {
|
65
|
+
params = Application.currentView.params;
|
66
|
+
}
|
67
|
+
$.hideLoader();
|
68
|
+
$.flash("A network error occurred.", params, true);
|
69
|
+
throw new Error('An error occurred.');
|
70
|
+
}
|
71
|
+
$.showLoader();
|
72
|
+
$.ajax({
|
73
|
+
url: view.url,
|
74
|
+
success: function(response) {
|
75
|
+
// If the server is unreachable, zepto calls `success`
|
76
|
+
// and then the `response` is empty. Catch it here and throw an error.
|
77
|
+
if (response === "") onError();
|
78
|
+
|
79
|
+
var response = $.highResifyLogosForRetinaAndAndroid(response);
|
80
|
+
|
81
|
+
view.buffer.html(response);
|
82
|
+
view.element = view.buffer.find('div').get(0);
|
83
|
+
view._evaluateDataAttribute();
|
84
|
+
Application.appendView(view);
|
85
|
+
$.hideLoader();
|
86
|
+
$.delayedLoad();
|
87
|
+
},
|
88
|
+
error: function() {
|
89
|
+
onError();
|
90
|
+
}
|
91
|
+
});
|
92
|
+
},
|
93
|
+
onClientCallback: function(name, value) {
|
94
|
+
console.log('BaseView.onClientCallback({' + name + ': ' + value + '})');
|
95
|
+
},
|
96
|
+
// If HTML returned from the server includes a `<data id="view_data" data=""></data>` element,
|
97
|
+
// this should contain an object literal (JSON string) with values that will be merged into
|
98
|
+
// the parameters for this view instance. This is used to pass back additional information
|
99
|
+
// from the server via the HTML. For example, when loading a player it might be useful to
|
100
|
+
// return the key for the player's team so that can be used when communicating with the client:
|
101
|
+
//
|
102
|
+
// <data id="view_data" data="{'title': '<%= @team.city_name %> <%= @team.team_name %>'}"></data>
|
103
|
+
//
|
104
|
+
// This will add the integer 1588 (correctly typed) under the property "team_key" to the
|
105
|
+
// parameters (`this.params`) for this view.
|
106
|
+
_evaluateDataAttribute: function() {
|
107
|
+
var view_data_el = Application.params.BUFFER_EL.find("#view_data");
|
108
|
+
if (view_data_el.size() === 0) return;
|
109
|
+
if (!view_data_el.attr('data')) return;
|
110
|
+
|
111
|
+
var data = eval.call(window, "(" + view_data_el.attr("data") + ")");
|
112
|
+
for (var key in data) {
|
113
|
+
// If you escape a non-string value, it is first converted to a string, which we don't want
|
114
|
+
this.params[key] = (typeof data[key] == "string") ? unescape(data[key]) : data[key];
|
115
|
+
}
|
116
|
+
}
|
117
|
+
});
|
@@ -0,0 +1,45 @@
|
|
1
|
+
// A very simple history implementation. Generates events on the `document.body` element when the
|
2
|
+
// hash changes, and includes a parsed object of parameters or a string from the hash.
|
3
|
+
|
4
|
+
var History = (function() {
|
5
|
+
|
6
|
+
var currentHash = null;
|
7
|
+
|
8
|
+
function getMemo() {
|
9
|
+
return currentHash.toParameters();
|
10
|
+
}
|
11
|
+
|
12
|
+
function getHash() {
|
13
|
+
return window.location.hash.substring(1);
|
14
|
+
}
|
15
|
+
|
16
|
+
function poll() {
|
17
|
+
var hash = getHash();
|
18
|
+
if (currentHash !== hash) {
|
19
|
+
currentHash = hash;
|
20
|
+
$(document.body).trigger("hashchange", [getMemo()]);
|
21
|
+
}
|
22
|
+
}
|
23
|
+
|
24
|
+
$(document).ready(function() {
|
25
|
+
currentHash = getHash();
|
26
|
+
|
27
|
+
if ('onhashchange' in window) {
|
28
|
+
$(window).on('hashchange', poll);
|
29
|
+
} else {
|
30
|
+
setInterval(poll, 50);
|
31
|
+
}
|
32
|
+
|
33
|
+
$(document.body).trigger("hashchange", [getMemo()]);
|
34
|
+
});
|
35
|
+
|
36
|
+
return {
|
37
|
+
add: function(params) {
|
38
|
+
window.location.hash = "#" + $.objToQueryStr(params);
|
39
|
+
},
|
40
|
+
currentHash: function() {
|
41
|
+
return getHash();
|
42
|
+
}
|
43
|
+
}
|
44
|
+
|
45
|
+
})();
|
@@ -0,0 +1,90 @@
|
|
1
|
+
// Mock client interface
|
2
|
+
var Mock = Class.extend({
|
3
|
+
initialize: function(client) {
|
4
|
+
this.client = client;
|
5
|
+
window.addEventListener("load", this._makeToolbar.bind(this), true);
|
6
|
+
},
|
7
|
+
_makeToolbar: function(){
|
8
|
+
var toolbar = document.createElement("div");
|
9
|
+
toolbar.id = "mock-toolbar-container";
|
10
|
+
// CSS is set in `mock.css`
|
11
|
+
toolbar.innerHTML = "<div id='mock-toolbar'>\
|
12
|
+
<div id='mock-left'></div>\
|
13
|
+
<div id='mock-center'></div>\
|
14
|
+
<div id='mock-right'></div>\
|
15
|
+
</div>";
|
16
|
+
|
17
|
+
document.body.insertBefore(toolbar, document.body.firstChild);
|
18
|
+
this.toolbar = toolbar;
|
19
|
+
}
|
20
|
+
});
|
21
|
+
|
22
|
+
var Mock = new Mock(Client);
|
23
|
+
|
24
|
+
Client.notify = function(obj) {
|
25
|
+
if (typeof obj.buttons !== 'undefined') {
|
26
|
+
this.makeButtons(obj.buttons);
|
27
|
+
}
|
28
|
+
if (typeof obj.title !== 'undefined') {
|
29
|
+
this.makeTitle(obj.title);
|
30
|
+
}
|
31
|
+
|
32
|
+
if (obj.action === "getFavesAndNotifs") {
|
33
|
+
Client.callback("favesAndNotifs", {
|
34
|
+
faves: Application.params.MOCK_FAVORITES,
|
35
|
+
notifs: Application.params.MOCK_NOTIFS
|
36
|
+
});
|
37
|
+
}
|
38
|
+
|
39
|
+
// Client.notify logs notifications to the console.
|
40
|
+
if (window.console && window.console.log) {
|
41
|
+
var arr = [];
|
42
|
+
for (var prop in obj) {
|
43
|
+
if (typeof obj[prop] !== "function") {
|
44
|
+
arr.push(escape(prop) + ": " + escape(obj[prop]));
|
45
|
+
}
|
46
|
+
}
|
47
|
+
console.log("Client.notify({ " + arr.join(", ") + " })");
|
48
|
+
}
|
49
|
+
};
|
50
|
+
|
51
|
+
Client.makeButtons = function(str) {
|
52
|
+
if (!str) return;
|
53
|
+
var specs = str.split(":");
|
54
|
+
if (specs.length != 2) {
|
55
|
+
alert("There should be 2 segments to a buttons specification");
|
56
|
+
} else {
|
57
|
+
makeButtonsForSection(specs[0], "mock-left");
|
58
|
+
makeButtonsForSection(specs[1], "mock-right");
|
59
|
+
}
|
60
|
+
function makeButtonsForSection(str, id) {
|
61
|
+
$('#'+id).hide();
|
62
|
+
if (str !== "") {
|
63
|
+
$('#'+id).show();
|
64
|
+
if (str === "NudgeNav") {
|
65
|
+
// Support for nudge nav in mock toolbar.
|
66
|
+
$('#'+id).html("<action name='nudge' value='prev'>↑</action> <action name='nudge' value='next'>↓</action>");
|
67
|
+
} else {
|
68
|
+
$('#'+id).html("<action name='callback' value=" + str + ">" + str + "</action>");
|
69
|
+
}
|
70
|
+
}
|
71
|
+
}
|
72
|
+
};
|
73
|
+
|
74
|
+
// Set the view title
|
75
|
+
Client.makeTitle = function(title) {
|
76
|
+
$("#mock-center").html(title);
|
77
|
+
};
|
78
|
+
|
79
|
+
setTimeout(function() {
|
80
|
+
$('#mock-toolbar').delegate('action', 'click', function(e) {
|
81
|
+
var name = $(e.target).attr('name');
|
82
|
+
var value = $(e.target).attr('value');
|
83
|
+
|
84
|
+
Application.onClientCallback(name, value);
|
85
|
+
});
|
86
|
+
}, 400);
|
87
|
+
|
88
|
+
Application.clientCallbackHandlers.push(function(name, value) {
|
89
|
+
if (value === "Back") history.back();
|
90
|
+
});
|
@@ -0,0 +1,18 @@
|
|
1
|
+
// Timer class for use with auto-updating of game status'.
|
2
|
+
var Timer = Class.extend({
|
3
|
+
initialize: function(func, period) {
|
4
|
+
this.func = func;
|
5
|
+
this.period = period;
|
6
|
+
this.interval = null;
|
7
|
+
},
|
8
|
+
// startNow: function() {
|
9
|
+
// this.func();
|
10
|
+
// this.interval = window.setInterval(this.func, this.period);
|
11
|
+
// },
|
12
|
+
start: function() {
|
13
|
+
this.interval = window.setInterval(this.func, this.period);
|
14
|
+
},
|
15
|
+
stop: function() {
|
16
|
+
window.clearInterval(this.interval);
|
17
|
+
}
|
18
|
+
});
|
@@ -0,0 +1,56 @@
|
|
1
|
+
// If your view implements an initialization function, that function will be passed a parameter
|
2
|
+
// object containing all the query parameters in the URL that triggered the view's creation, plus
|
3
|
+
// all of those values that were assigned to the view when it was registered and bound to a name.
|
4
|
+
// It does not need to hold on to these values (although the base implementation of view does, as
|
5
|
+
// `this.params`). At the end of a view's create method, it should have inserted a dom element into
|
6
|
+
// the body of the page. This will be assigned as the "element" property to the view by the application,
|
7
|
+
// as it needs to be referenced outside your view class.
|
8
|
+
var View = Class.extend({
|
9
|
+
// This method should create (by any means desirable) a DOM element and insert it into the page.
|
10
|
+
// Our base implementation queries for an HTML fragment from the server, but this is up to
|
11
|
+
// your view implementation.
|
12
|
+
create: function() {
|
13
|
+
throw new Error("Create method not implemented in subclass");
|
14
|
+
},
|
15
|
+
// Title of this view. We may not actually use titles in this version of the application,
|
16
|
+
// but we needed to provide this in the past.
|
17
|
+
getTitle: function() {
|
18
|
+
throw new Error("getTitle method not implemented in subclass");
|
19
|
+
},
|
20
|
+
// The name of the view that is used to log metrics to Google Analytics. The view
|
21
|
+
// may also provide additional calls to `Client.notify({'metric': 'metricName'})` if it updates
|
22
|
+
// internally (changing tabs, for example).
|
23
|
+
getMetric: function() {
|
24
|
+
throw new Error("getMetric method not implemented in subclass");
|
25
|
+
},
|
26
|
+
getButtons: function() {
|
27
|
+
throw new Error("getButtons method not implemented in subclass");
|
28
|
+
},
|
29
|
+
// Send off any necessary notifications to the client. This avoids and issue on iOS where
|
30
|
+
// two notifications send right after one another causes one of them to fail.
|
31
|
+
getAction: function() {
|
32
|
+
throw new Error("getAction method not implemented in subclass");
|
33
|
+
},
|
34
|
+
// Tell the client what a filtereable view is filtered to.
|
35
|
+
getFilter: function() {
|
36
|
+
throw new Error("getFilter method not implemented in subclass");
|
37
|
+
},
|
38
|
+
// Tell the client what section we are in.
|
39
|
+
getSection: function() {
|
40
|
+
throw new Error("getSection method not implemented in subclass");
|
41
|
+
},
|
42
|
+
// Called before the view is appended to the page.
|
43
|
+
beforeViewAppended: function() {
|
44
|
+
|
45
|
+
},
|
46
|
+
// Called after the view is appended into the page. Either if comes from the cache, or if
|
47
|
+
// it is from a get request.
|
48
|
+
afterViewAppended: function() {
|
49
|
+
|
50
|
+
}
|
51
|
+
// The client has executed a callback on the web page, to pass a value to the page
|
52
|
+
// or to execute some functionality.
|
53
|
+
/*
|
54
|
+
,onClientCallback( name, value ) {}
|
55
|
+
*/
|
56
|
+
});
|