sports_db 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
});
|