golf 0.0.8 → 0.0.9
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/.gitignore +1 -0
- data/bin/golf +0 -0
- data/lib/golf/cli.rb +1 -1
- data/lib/golf/rack.rb +191 -3
- data/lib/golf/version.rb +1 -1
- data/resources/app_error.html +60 -0
- data/{template/golfapp → resources}/controller.js +0 -0
- data/resources/index.html +61 -0
- data/resources/jquery.address.js +439 -0
- data/resources/jquery.golf.js +943 -0
- data/resources/jquery.js +4376 -0
- data/resources/welcome2golf.html +50 -0
- data/{template → templates/new}/404.txt +0 -0
- data/{template → templates/new}/Gemfile +2 -1
- data/{template/golfapp → templates/new}/components/HelloWorld/HelloWorld.html +0 -0
- data/{template → templates/new}/config.ru +0 -1
- data/templates/new/controller.js +7 -0
- data/test/data/jquery.golf.js +1 -0
- data/test/test_rack.rb +9 -0
- metadata +13 -6
@@ -0,0 +1,943 @@
|
|
1
|
+
(function($) {
|
2
|
+
|
3
|
+
function toJson(obj) {
|
4
|
+
switch (typeof obj) {
|
5
|
+
case 'object':
|
6
|
+
if (obj) {
|
7
|
+
var list = [];
|
8
|
+
if (obj instanceof Array) {
|
9
|
+
for (var i=0;i < obj.length;i++) {
|
10
|
+
list.push(toJson(obj[i]));
|
11
|
+
}
|
12
|
+
return '[' + list.join(',') + ']';
|
13
|
+
} else {
|
14
|
+
for (var prop in obj) {
|
15
|
+
list.push('"' + prop + '":' + toJson(obj[prop]));
|
16
|
+
}
|
17
|
+
return '{' + list.join(',') + '}';
|
18
|
+
}
|
19
|
+
} else {
|
20
|
+
return 'null';
|
21
|
+
}
|
22
|
+
case 'string':
|
23
|
+
return '"' + obj.replace(/(["'])/g, '\\$1') + '"';
|
24
|
+
case 'number':
|
25
|
+
case 'boolean':
|
26
|
+
return new String(obj);
|
27
|
+
}
|
28
|
+
}
|
29
|
+
|
30
|
+
function Component() {
|
31
|
+
this._dom = null;
|
32
|
+
this._$ = null;
|
33
|
+
this.hide = function() {
|
34
|
+
this._dom.hide(Array.prototype.slice.call(arguments));
|
35
|
+
};
|
36
|
+
this.show = function() {
|
37
|
+
this._dom.show(Array.prototype.slice.call(arguments));
|
38
|
+
};
|
39
|
+
}
|
40
|
+
|
41
|
+
function Debug(prefix) {
|
42
|
+
return function(text) {
|
43
|
+
text = prefix+": "+text;
|
44
|
+
window.devmode = true;
|
45
|
+
if (window.devmode && window.console && window.console.log)
|
46
|
+
console.log(text);
|
47
|
+
else if (window.serverside)
|
48
|
+
alert(text);
|
49
|
+
};
|
50
|
+
}
|
51
|
+
|
52
|
+
function $local(selector, root) {
|
53
|
+
return $(root)
|
54
|
+
.find("*")
|
55
|
+
.andSelf()
|
56
|
+
.filter(selector)
|
57
|
+
.not($(".component *", root).get())
|
58
|
+
.not($("* .component", root).get());
|
59
|
+
}
|
60
|
+
|
61
|
+
function checkForReservedClass(elems, shutup) {
|
62
|
+
if (! $.golf.reservedClassChecking || window.forcebot)
|
63
|
+
return [];
|
64
|
+
var RESERVED_CLASSES = [ "component", "golfbody", "golfproxylink" ];
|
65
|
+
var badclass = (
|
66
|
+
(typeof elems == "string")
|
67
|
+
? $.map(RESERVED_CLASSES, function(c) {
|
68
|
+
return (c == elems) ? elems : null;
|
69
|
+
})
|
70
|
+
: $.map(RESERVED_CLASSES, function(c) {
|
71
|
+
return elems.hasClass(c) ? c : null;
|
72
|
+
})
|
73
|
+
);
|
74
|
+
|
75
|
+
if (badclass.length && !shutup)
|
76
|
+
d("WARN: using, adding, or removing reserved class names: "
|
77
|
+
+ badclass.join(","));
|
78
|
+
return badclass;
|
79
|
+
}
|
80
|
+
|
81
|
+
function doCall(obj, jQuery, $, argv, js, d) {
|
82
|
+
d = !!d ? d : window.d;
|
83
|
+
if (js.length > 10) {
|
84
|
+
var f;
|
85
|
+
eval("f = "+js);
|
86
|
+
f.apply(obj, argv);
|
87
|
+
}
|
88
|
+
}
|
89
|
+
|
90
|
+
/* parseUri is based on work (c) 2007 Steven Levithan <stevenlevithan.com> */
|
91
|
+
|
92
|
+
function parseUri(str) {
|
93
|
+
var o = {
|
94
|
+
strictMode: true,
|
95
|
+
key: ["source","protocol","authority","userInfo","user","password",
|
96
|
+
"host","port","relative","path","directory","file","query","anchor"],
|
97
|
+
q: {
|
98
|
+
name: "queryKey",
|
99
|
+
parser: /(?:^|&)([^&=]*)=?([^&]*)/g
|
100
|
+
},
|
101
|
+
parser: {
|
102
|
+
strict: /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/,
|
103
|
+
loose: /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/
|
104
|
+
}
|
105
|
+
};
|
106
|
+
var m = o.parser[o.strictMode ? "strict" : "loose"].exec(str),
|
107
|
+
uri = {},
|
108
|
+
i = 14;
|
109
|
+
|
110
|
+
while (i--) uri[o.key[i]] = m[i] || "";
|
111
|
+
|
112
|
+
uri[o.q.name] = {};
|
113
|
+
uri[o.key[12]].replace(o.q.parser, function ($0, $1, $2) {
|
114
|
+
if ($1) uri[o.q.name][$1] = $2;
|
115
|
+
});
|
116
|
+
|
117
|
+
return uri;
|
118
|
+
}
|
119
|
+
|
120
|
+
/* jss is based on: JSS - 0.4 by Andy Kent */
|
121
|
+
|
122
|
+
var jss = {
|
123
|
+
|
124
|
+
mark: function(elem) {
|
125
|
+
var cpdom;
|
126
|
+
|
127
|
+
try {
|
128
|
+
cpdom = $(elem).parents(".component").eq(0);
|
129
|
+
|
130
|
+
if (cpdom.size() == 0 || cpdom.data("_golf_constructing"))
|
131
|
+
return;
|
132
|
+
}
|
133
|
+
catch (x) {
|
134
|
+
d("WARN: can't do mark: "+x);
|
135
|
+
return;
|
136
|
+
}
|
137
|
+
|
138
|
+
cpdom.data("_golf_jss_dirty", true);
|
139
|
+
if ($.golf.jssTimeout >= 0)
|
140
|
+
setTimeout(function() { jss.doit(elem) }, 10);
|
141
|
+
else jss.doit(elem);
|
142
|
+
},
|
143
|
+
|
144
|
+
doit: function(elem, force) {
|
145
|
+
var cpdom, cpname, data, parsed;
|
146
|
+
|
147
|
+
if ((serverside && !force) || window.forcebot)
|
148
|
+
return;
|
149
|
+
|
150
|
+
try {
|
151
|
+
cpdom = $(elem).parents(".component").eq(0);
|
152
|
+
|
153
|
+
if (cpdom.size() == 0 || cpdom.data("_golf_constructing")
|
154
|
+
|| !cpdom.data("_golf_jss_dirty"))
|
155
|
+
return;
|
156
|
+
|
157
|
+
cpdom.removeData("_golf_jss_dirty");
|
158
|
+
|
159
|
+
cpname = cpdom.attr("class").split(" ")[1].replace(/-/g, ".");
|
160
|
+
data = $.golf.components[cpname].css;
|
161
|
+
parsed = this.parse(data);
|
162
|
+
}
|
163
|
+
catch (x) {
|
164
|
+
d("WARN: can't do jss: "+x);
|
165
|
+
return;
|
166
|
+
}
|
167
|
+
|
168
|
+
$local("*", cpdom).each(
|
169
|
+
function() {
|
170
|
+
var jself = $(this);
|
171
|
+
for (var i in jself.data("_golf_jss_log"))
|
172
|
+
jself._golf_css(i, "");
|
173
|
+
jself.data("_golf_jss_log", {});
|
174
|
+
jself.data("_golf_jss_spc", {});
|
175
|
+
jself._golf_css(jself.data("_golf_css_log"));
|
176
|
+
}
|
177
|
+
);
|
178
|
+
|
179
|
+
$.each(parsed, function() {
|
180
|
+
var selectors = this.selector;
|
181
|
+
var attrs = this.attributes;
|
182
|
+
|
183
|
+
$.each(
|
184
|
+
selectors.split(/ *, */),
|
185
|
+
function(k, selector) {
|
186
|
+
var parser = /([a-z][a-z0-9]*|\*)|(#[_a-z][-_a-z0-9]*)|(\.[_a-z][-_a-z0-9]*|\[[^\]]+\])|(:[-a-z]+)|( *[>+~] *| +)/gi;
|
187
|
+
var pseudo = /^:(first-(line|letter)|before|after)$/;
|
188
|
+
var base=32,TAG=1,ID=2,ATTR=3,PSEUDO=4,COMBI=5,weight=0,m;
|
189
|
+
|
190
|
+
parser.lastIndex = 0;
|
191
|
+
|
192
|
+
while (m = parser.exec(selector)) {
|
193
|
+
if (m[ID]) {
|
194
|
+
weight += 32*32;
|
195
|
+
} else if (m[ATTR]) {
|
196
|
+
weight += 32;
|
197
|
+
} else if (m[PSEUDO]) {
|
198
|
+
weight += (m[PSEUDO].match(pseudo) ? 1 : 10);
|
199
|
+
} else if (m[TAG]) {
|
200
|
+
weight += 1;
|
201
|
+
}
|
202
|
+
}
|
203
|
+
|
204
|
+
$local(selector, cpdom).each(
|
205
|
+
function() {
|
206
|
+
var jself=$(this), log, i;
|
207
|
+
|
208
|
+
if (!jself.data("_golf_jss_log"))
|
209
|
+
jself.data("_golf_jss_log", {});
|
210
|
+
if (!jself.data("_golf_jss_spc"))
|
211
|
+
jself.data("_golf_jss_spc", {});
|
212
|
+
|
213
|
+
log = jself.data("_golf_jss_spc");
|
214
|
+
for (i in attrs) {
|
215
|
+
if (log[i] > weight)
|
216
|
+
delete attrs[i];
|
217
|
+
else
|
218
|
+
log[i] = weight;
|
219
|
+
}
|
220
|
+
|
221
|
+
$.extend(jself.data("_golf_jss_spc"), log);
|
222
|
+
$.extend(jself.data("_golf_jss_log"), attrs);
|
223
|
+
|
224
|
+
jself._golf_css(attrs);
|
225
|
+
|
226
|
+
log = jself.data("_golf_css_log");
|
227
|
+
for (i in log)
|
228
|
+
jself._golf_css(jself.data("_golf_css_log"));
|
229
|
+
}
|
230
|
+
);
|
231
|
+
}
|
232
|
+
);
|
233
|
+
});
|
234
|
+
},
|
235
|
+
|
236
|
+
// ---
|
237
|
+
// Ultra lightweight CSS parser, only works with 100% valid css
|
238
|
+
// files, no support for hacks etc.
|
239
|
+
// ---
|
240
|
+
|
241
|
+
sanitize: function(content) {
|
242
|
+
if(!content) return '';
|
243
|
+
var c = content.replace(/[\n\r]/gi,''); // remove newlines
|
244
|
+
c = c.replace(/\/\*.+?\*\//gi,''); // remove comments
|
245
|
+
return c;
|
246
|
+
},
|
247
|
+
|
248
|
+
parse: function(content) {
|
249
|
+
var c = this.sanitize(content);
|
250
|
+
var tree = []; // this is the css tree that is built up
|
251
|
+
c = c.match(/.+?\{.+?\}/gi); // seperate out selectors
|
252
|
+
if(!c) return [];
|
253
|
+
for(var i=0;i<c.length;i++) // loop through selectors & parse attributes
|
254
|
+
if(c[i])
|
255
|
+
tree.push( {
|
256
|
+
selector: this.parseSelectorName(c[i]),
|
257
|
+
attributes: this.parseAttributes(c[i])
|
258
|
+
} );
|
259
|
+
return tree;
|
260
|
+
},
|
261
|
+
|
262
|
+
parseSelectorName: function(content) { // extract the selector
|
263
|
+
return $.trim(content.match(/^.+?\{/)[0].replace('{',''));
|
264
|
+
},
|
265
|
+
|
266
|
+
parseAttributes: function(content) {
|
267
|
+
var attributes = {};
|
268
|
+
c = content.match(/\{.+?\}/)[0].replace(/[\{\}]/g,'').split(';').slice(0,-1);
|
269
|
+
for(var i=0;i<c.length; i++){
|
270
|
+
if(c[i]){
|
271
|
+
c[i] = c[i].split(':');
|
272
|
+
attributes[$.trim(c[i][0])] = $.trim(c[i][1]);
|
273
|
+
};
|
274
|
+
};
|
275
|
+
return attributes;
|
276
|
+
}
|
277
|
+
|
278
|
+
};
|
279
|
+
|
280
|
+
function makePkg(pkg, obj) {
|
281
|
+
if (!obj)
|
282
|
+
obj = Component;
|
283
|
+
|
284
|
+
if (!pkg || !pkg.length)
|
285
|
+
return obj;
|
286
|
+
|
287
|
+
var r = /^([^.]+)((\.)([^.]+.*))?$/;
|
288
|
+
var m = pkg.match(r);
|
289
|
+
|
290
|
+
if (!m)
|
291
|
+
throw "bad package: '"+pkg+"'";
|
292
|
+
|
293
|
+
if (!obj[m[1]])
|
294
|
+
obj[m[1]] = {};
|
295
|
+
|
296
|
+
return makePkg(m[4], obj[m[1]]);
|
297
|
+
}
|
298
|
+
|
299
|
+
function onLoad() {
|
300
|
+
if (serverside)
|
301
|
+
$("noscript").remove();
|
302
|
+
|
303
|
+
if (urlHash && !location.hash)
|
304
|
+
window.location.replace(servletUrl + "#" + urlHash);
|
305
|
+
|
306
|
+
$.address.change(function(evnt) {
|
307
|
+
onHistoryChange(evnt.value);
|
308
|
+
});
|
309
|
+
}
|
310
|
+
|
311
|
+
var onHistoryChange = (function() {
|
312
|
+
var lastHash = "";
|
313
|
+
return function(hash, b) {
|
314
|
+
|
315
|
+
d("history change => '"+hash+"'");
|
316
|
+
if (hash && hash == "/")
|
317
|
+
return $.golf.location(String($.golf.defaultRoute));
|
318
|
+
|
319
|
+
if (hash && hash.charAt(0) != "/")
|
320
|
+
return $.golf.location("/"+hash);
|
321
|
+
|
322
|
+
if (hash && hash != lastHash) {
|
323
|
+
lastHash = hash;
|
324
|
+
hash = hash.replace(/^\/+/, "/");
|
325
|
+
$.golf.location.hash = String(hash+"/").replace(/\/+$/, "/");
|
326
|
+
window.location.hash = "#"+$.golf.location.hash;
|
327
|
+
$.golf.route(hash, b);
|
328
|
+
}
|
329
|
+
};
|
330
|
+
})();
|
331
|
+
|
332
|
+
function prepare(p) {
|
333
|
+
$("*", p).add([ p ]).each(function() {
|
334
|
+
// FIXME: verify whether 'this' is jQuery obj or DOM elem?
|
335
|
+
var jself = $(this);
|
336
|
+
var eself = jself.get()[0];
|
337
|
+
|
338
|
+
if (jself.data("_golf_prepared"))
|
339
|
+
return;
|
340
|
+
|
341
|
+
jself.data("_golf_prepared", true);
|
342
|
+
|
343
|
+
// makes hrefs in links work in both client and proxy modes
|
344
|
+
if (eself.tagName === "A")
|
345
|
+
jself.href(eself.href);
|
346
|
+
});
|
347
|
+
return p;
|
348
|
+
}
|
349
|
+
|
350
|
+
function componentConstructor(name) {
|
351
|
+
var result = function() {
|
352
|
+
var argv = Array.prototype.slice.call(arguments);
|
353
|
+
var obj = this;
|
354
|
+
var cmp = $.golf.components[name];
|
355
|
+
|
356
|
+
d("Instantiating component '"+$.golf.components[name].name+"'");
|
357
|
+
|
358
|
+
// $fake: the component-localized jQuery
|
359
|
+
|
360
|
+
var $fake = function( selector, context ) {
|
361
|
+
var isHtml = /^[^<]*(<(.|\s)+>)[^>]*$/;
|
362
|
+
|
363
|
+
// if it's a function then immediately execute it (DOM loading
|
364
|
+
// is guaranteed to be complete by the time this runs)
|
365
|
+
if ($.isFunction(selector)) {
|
366
|
+
selector();
|
367
|
+
return;
|
368
|
+
}
|
369
|
+
|
370
|
+
// if it's not a css selector then passthru to jQ
|
371
|
+
if (typeof selector != "string" || selector.match(isHtml))
|
372
|
+
return new $(selector);
|
373
|
+
|
374
|
+
// it's a css selector
|
375
|
+
if (context != null)
|
376
|
+
return $(context)
|
377
|
+
.find(selector)
|
378
|
+
.not($(".component *", obj._dom).get())
|
379
|
+
.not($("* .component", obj._dom).get());
|
380
|
+
else
|
381
|
+
return $(obj._dom)
|
382
|
+
.find("*")
|
383
|
+
.andSelf()
|
384
|
+
.filter(selector)
|
385
|
+
.not($(".component *", obj._dom).get())
|
386
|
+
.not($("* .component", obj._dom).get());
|
387
|
+
};
|
388
|
+
|
389
|
+
$.extend($fake, $);
|
390
|
+
$fake.prototype = $fake.fn;
|
391
|
+
|
392
|
+
$fake.component = cmp;
|
393
|
+
|
394
|
+
$fake.require = $.golf.require($fake);
|
395
|
+
|
396
|
+
if (cmp) {
|
397
|
+
obj._dom = cmp.dom.clone();
|
398
|
+
obj._dom.data("_golf_constructing", true);
|
399
|
+
obj.require = $fake.require;
|
400
|
+
checkForReservedClass(obj._dom.children().find("*"));
|
401
|
+
doCall(obj, $fake, $fake, argv, cmp.js, Debug(name));
|
402
|
+
obj._dom.removeData("_golf_constructing");
|
403
|
+
jss.mark(obj._dom.children().eq(0));
|
404
|
+
jss.doit(obj._dom.children().eq(0));
|
405
|
+
} else {
|
406
|
+
throw "can't find component: "+name;
|
407
|
+
}
|
408
|
+
};
|
409
|
+
result.prototype = new Component();
|
410
|
+
return result;
|
411
|
+
}
|
412
|
+
|
413
|
+
// globals
|
414
|
+
|
415
|
+
window.d = Debug("GOLF");
|
416
|
+
window.Debug = Debug;
|
417
|
+
window.Component = Component;
|
418
|
+
|
419
|
+
// serverside mods to jQuery
|
420
|
+
|
421
|
+
if (serverside) {
|
422
|
+
|
423
|
+
if (!window.forcebot) {
|
424
|
+
$.fx.off = true;
|
425
|
+
|
426
|
+
$.fn.fadeIn = $.fn.slideDown = function(speed, callback) {
|
427
|
+
return $.fn.show.call(this, 0, callback);
|
428
|
+
};
|
429
|
+
|
430
|
+
$.fn.fadeOut = $.fn.slideUp = function(speed, callback) {
|
431
|
+
return $.fn.hide.call(this, 0, callback);
|
432
|
+
};
|
433
|
+
|
434
|
+
// this is problematic because the js css manipulations are not carried
|
435
|
+
// over in proxy mode; needs to be in a style tag maybe
|
436
|
+
//(function(fadeTo) {
|
437
|
+
// jQuery.fn.fadeTo = function(speed, opacity, callback) {
|
438
|
+
// return fadeTo.call(this, 0, opacity, callback);
|
439
|
+
// };
|
440
|
+
//})(jQuery.fn.fadeTo);
|
441
|
+
|
442
|
+
$.fn.slideToggle = function(speed, callback) {
|
443
|
+
return $.fn.toggle.call(this, 0, callback);
|
444
|
+
};
|
445
|
+
|
446
|
+
$.fn.show = (function(show) {
|
447
|
+
return function(speed, callback) {
|
448
|
+
return show.call(this, 0, callback);
|
449
|
+
};
|
450
|
+
})($.fn.show);
|
451
|
+
|
452
|
+
$.fn.hide = (function(hide) {
|
453
|
+
return function(speed, callback) {
|
454
|
+
return hide.call(this, 0, callback);
|
455
|
+
};
|
456
|
+
})($.fn.hide);
|
457
|
+
|
458
|
+
$.fn.bind = (function(bind) {
|
459
|
+
var lastId = 0;
|
460
|
+
return function(name, fn) {
|
461
|
+
var jself = $(this);
|
462
|
+
var _href = jself.attr("href");
|
463
|
+
var _golfid = jself.attr("golfid");
|
464
|
+
if (name == "click") {
|
465
|
+
if (!_golfid) {
|
466
|
+
++lastId;
|
467
|
+
jself.attr("golfid", lastId);
|
468
|
+
}
|
469
|
+
if (_href) {
|
470
|
+
jself.data("_golf_oldfn", fn);
|
471
|
+
|
472
|
+
if (_href && _href.charAt(0) != "#")
|
473
|
+
jself.data("_golf_oldhref",
|
474
|
+
"/"+_href.replace(/^(http:\/\/)?([^\/]\/?)*\/\//g, ""));
|
475
|
+
else if (jself.attr("href"))
|
476
|
+
jself.data("_golf_oldhref", _href.replace(/^#/, ""));
|
477
|
+
|
478
|
+
jself.attr({
|
479
|
+
rel: "nofollow",
|
480
|
+
href: "?target="+lastId+"&event=onclick"
|
481
|
+
});
|
482
|
+
fn = function() {
|
483
|
+
var argv = Array.prototype.slice.call(arguments);
|
484
|
+
if ($(this).data("_golf_oldfn").apply(jss, argv) !== false) {
|
485
|
+
$(this).attr("href", servletUrl+$(this).data("_golf_oldhref"));
|
486
|
+
$.golf.location($(this).data("_golf_oldhref"));
|
487
|
+
}
|
488
|
+
};
|
489
|
+
} else {
|
490
|
+
var a = "<a rel='nofollow' href='?target="+lastId+
|
491
|
+
"&event=onclick'></a>";
|
492
|
+
jself.wrap(a);
|
493
|
+
jself._golf_addClass("golfproxylink");
|
494
|
+
}
|
495
|
+
} else if (name == "submit") {
|
496
|
+
if (!_golfid) {
|
497
|
+
++lastId;
|
498
|
+
jself.attr("golfid", lastId);
|
499
|
+
jself.append(
|
500
|
+
"<input type='hidden' name='event' value='onsubmit'/>");
|
501
|
+
jself.append(
|
502
|
+
"<input type='hidden' name='target' value='"+lastId+"'/>");
|
503
|
+
if (!$.golf.events[lastId])
|
504
|
+
$.golf.events[lastId] = [];
|
505
|
+
}
|
506
|
+
$.golf.events[jself.attr("golfid")].push(fn);
|
507
|
+
}
|
508
|
+
return bind.call(jself, name, fn);
|
509
|
+
};
|
510
|
+
})($.fn.bind);
|
511
|
+
|
512
|
+
$.fn.trigger = (function(trigger) {
|
513
|
+
return function(type, data) {
|
514
|
+
var jself = $(this);
|
515
|
+
// FIXME: this is here because hunit stops firing js submit events
|
516
|
+
if (type == "submit") {
|
517
|
+
var tmp = $.golf.events[jself.attr("golfid")];
|
518
|
+
return $.each(tmp, function(){
|
519
|
+
this.call(jself, type, data);
|
520
|
+
});
|
521
|
+
} else {
|
522
|
+
return trigger.call($(this), type, data);
|
523
|
+
}
|
524
|
+
};
|
525
|
+
})($.fn.trigger);
|
526
|
+
}
|
527
|
+
|
528
|
+
$.fn.val = (function(val) {
|
529
|
+
return function(newVal) {
|
530
|
+
if (arguments.length == 0)
|
531
|
+
return $.trim(val.call($(this)));
|
532
|
+
else
|
533
|
+
return val.call($(this), newVal);
|
534
|
+
};
|
535
|
+
})($.fn.val);
|
536
|
+
|
537
|
+
$.ajax = (function(ajax) {
|
538
|
+
return function(options) {
|
539
|
+
options.async = false;
|
540
|
+
return ajax(options);
|
541
|
+
};
|
542
|
+
})($.ajax);
|
543
|
+
|
544
|
+
} else {
|
545
|
+
|
546
|
+
$.fn.bind = (function(bind) {
|
547
|
+
var lastId = 0;
|
548
|
+
return function(name, fn) {
|
549
|
+
var jself = $(this);
|
550
|
+
if (name == "submit") {
|
551
|
+
var oldfn = fn;
|
552
|
+
fn = function() {
|
553
|
+
var argv = Array.prototype.slice.call(arguments);
|
554
|
+
try {
|
555
|
+
oldfn.apply(this, argv);
|
556
|
+
} catch(e) {
|
557
|
+
$.golf.errorPage("Oops!", "<code>"+e.toString()+"</code>");
|
558
|
+
}
|
559
|
+
return false;
|
560
|
+
};
|
561
|
+
}
|
562
|
+
return bind.call(jself, name, fn);
|
563
|
+
};
|
564
|
+
})($.fn.bind);
|
565
|
+
|
566
|
+
}
|
567
|
+
|
568
|
+
// install overrides on jQ DOM manipulation methods to accomodate components
|
569
|
+
|
570
|
+
(function() {
|
571
|
+
|
572
|
+
$.each(
|
573
|
+
[
|
574
|
+
"append",
|
575
|
+
"prepend",
|
576
|
+
"after",
|
577
|
+
"before",
|
578
|
+
"replaceWith"
|
579
|
+
],
|
580
|
+
function(k,v) {
|
581
|
+
$.fn["_golf_"+v] = $.fn[v];
|
582
|
+
$.fn[v] = function(a) {
|
583
|
+
var e = $(a instanceof Component ? a._dom : a);
|
584
|
+
if (! (a instanceof Component))
|
585
|
+
checkForReservedClass(e);
|
586
|
+
|
587
|
+
prepare(e);
|
588
|
+
var ret = $.fn["_golf_"+v].call($(this), e);
|
589
|
+
$(e.parent()).each(function() {
|
590
|
+
$(this).removeData("_golf_prepared");
|
591
|
+
});
|
592
|
+
jss.mark(this);
|
593
|
+
if (a instanceof Component && a.onAppend)
|
594
|
+
a.onAppend();
|
595
|
+
return $(this);
|
596
|
+
};
|
597
|
+
}
|
598
|
+
);
|
599
|
+
|
600
|
+
$.fn._golf_remove = $.fn.remove;
|
601
|
+
$.fn.remove = function() {
|
602
|
+
$("*", this).add([this]).each(function() {
|
603
|
+
if ($(this).attr("golfid"))
|
604
|
+
$.golf.events[$(this).attr("golfid")] = [];
|
605
|
+
});
|
606
|
+
return $.fn._golf_remove.call(this);
|
607
|
+
};
|
608
|
+
|
609
|
+
$.each(
|
610
|
+
[
|
611
|
+
"addClass",
|
612
|
+
"removeClass",
|
613
|
+
"toggleClass"
|
614
|
+
],
|
615
|
+
function(k,v) {
|
616
|
+
$.fn["_golf_"+v] = $.fn[v];
|
617
|
+
$.fn[v] = function() {
|
618
|
+
// FIXME need to cover the case of $(thing).removeClass() with no
|
619
|
+
// parameters and when `thing` _has_ a reserved class already
|
620
|
+
var putback = {};
|
621
|
+
var self = this;
|
622
|
+
if (arguments.length) {
|
623
|
+
checkForReservedClass(arguments[0]);
|
624
|
+
} else if (v == "removeClass") {
|
625
|
+
$.map(checkForReservedClass(this, true), function(c) {
|
626
|
+
putback[c] = $.map(self, function(e) {
|
627
|
+
return $(e).hasClass(c) ? e : null;
|
628
|
+
});
|
629
|
+
});
|
630
|
+
}
|
631
|
+
var ret = $.fn["_golf_"+v].apply(this, arguments);
|
632
|
+
for (var i in putback)
|
633
|
+
for (var j in putback[i])
|
634
|
+
$(putback[i][j])._golf_addClass(i);
|
635
|
+
jss.mark(this);
|
636
|
+
return ret;
|
637
|
+
};
|
638
|
+
}
|
639
|
+
);
|
640
|
+
|
641
|
+
$.fn._golf_css = $.fn.css;
|
642
|
+
$.fn.css = function() {
|
643
|
+
var log = this.data("_golf_css_log") || {};
|
644
|
+
|
645
|
+
if (arguments.length > 0) {
|
646
|
+
if (typeof arguments[0] == "string") {
|
647
|
+
if (arguments.length == 1)
|
648
|
+
return this._golf_css(arguments[0]);
|
649
|
+
else
|
650
|
+
log[arguments[0]] = arguments[1];
|
651
|
+
} else {
|
652
|
+
$.extend(log, arguments[0]);
|
653
|
+
}
|
654
|
+
|
655
|
+
for (var i in log)
|
656
|
+
if (log[i] == "")
|
657
|
+
delete log[i];
|
658
|
+
|
659
|
+
this.data("_golf_css_log", log);
|
660
|
+
var ret = this._golf_css(arguments[0], arguments[1]);
|
661
|
+
jss.mark(this);
|
662
|
+
return ret;
|
663
|
+
}
|
664
|
+
return this;
|
665
|
+
};
|
666
|
+
|
667
|
+
$.fn.href = (function() {
|
668
|
+
var uri2;
|
669
|
+
return function(uri) {
|
670
|
+
var uri1 = parseUri(uri);
|
671
|
+
var curHash = window.location.hash.replace(/^#/, "");
|
672
|
+
var anchor;
|
673
|
+
|
674
|
+
if (!uri2)
|
675
|
+
uri2 = parseUri(servletUrl);
|
676
|
+
|
677
|
+
if (uri1.protocol == uri2.protocol
|
678
|
+
&& uri1.authority == uri2.authority
|
679
|
+
&& uri1.directory.substr(0, uri2.directory.length)
|
680
|
+
== uri2.directory) {
|
681
|
+
if (uri1.queryKey.path) {
|
682
|
+
if (cloudfrontDomain.length)
|
683
|
+
uri = cloudfrontDomain[0]+uri.queryKey.path;
|
684
|
+
} else if (uri1.anchor) {
|
685
|
+
if (!uri1.anchor.match(/^\//)) {
|
686
|
+
anchor = (curHash ? curHash : "/") + uri1.anchor;
|
687
|
+
uri = "#"+anchor;
|
688
|
+
} else {
|
689
|
+
anchor = uri1.anchor;
|
690
|
+
}
|
691
|
+
if (serverside)
|
692
|
+
this.attr("href", servletUrl + anchor);
|
693
|
+
}
|
694
|
+
}
|
695
|
+
};
|
696
|
+
})();
|
697
|
+
})();
|
698
|
+
|
699
|
+
// main jQ golf object
|
700
|
+
|
701
|
+
$.golf = {
|
702
|
+
|
703
|
+
jssTimeout: 10,
|
704
|
+
|
705
|
+
controller: [],
|
706
|
+
|
707
|
+
defaultRoute: "/home/",
|
708
|
+
|
709
|
+
reservedClassChecking: true,
|
710
|
+
|
711
|
+
loaded: false,
|
712
|
+
|
713
|
+
events: [],
|
714
|
+
|
715
|
+
singleton: {},
|
716
|
+
|
717
|
+
toJson: toJson,
|
718
|
+
|
719
|
+
jss: function() {
|
720
|
+
var argv = Array.prototype.slice.call(arguments);
|
721
|
+
jss.doit.apply(jss, argv);
|
722
|
+
},
|
723
|
+
|
724
|
+
location: function(hash) {
|
725
|
+
if (!!hash)
|
726
|
+
$.address.value(hash);
|
727
|
+
else
|
728
|
+
return $.golf.location.hash;
|
729
|
+
},
|
730
|
+
|
731
|
+
htmlEncode: function(text) {
|
732
|
+
return text.replace(/&/g, "&")
|
733
|
+
.replace(/</g, "<")
|
734
|
+
.replace(/>/g, ">")
|
735
|
+
.replace(/"/g, """);
|
736
|
+
},
|
737
|
+
|
738
|
+
addComponent: function(data, name) {
|
739
|
+
var orig = data;
|
740
|
+
var js =
|
741
|
+
data
|
742
|
+
.replace(/^(.|\n)*<script +type *= *("text\/golf"|'text\/golf')>/, "")
|
743
|
+
.replace(/<\/script>(.|\n)*$/, "");
|
744
|
+
var css =
|
745
|
+
data
|
746
|
+
.replace(/^(.|\n)*<style +type *= *("text\/golf"|'text\/golf')>/, "")
|
747
|
+
.replace(/<\/style>(.|\n)*$/, "");
|
748
|
+
var html = $("<div/>")._golf_append(
|
749
|
+
$(data)._golf_addClass("component")
|
750
|
+
._golf_addClass(name.replace(".", "-"))
|
751
|
+
);
|
752
|
+
html.find("style,script").remove();
|
753
|
+
var cmp = {
|
754
|
+
"orig" : orig,
|
755
|
+
"name" : name,
|
756
|
+
"html" : html.html(),
|
757
|
+
"dom" : $(html.html()),
|
758
|
+
"css" : css,
|
759
|
+
"js" : js
|
760
|
+
};
|
761
|
+
var m, pkg;
|
762
|
+
|
763
|
+
$.golf.components[name] = cmp;
|
764
|
+
|
765
|
+
if (!(m = name.match(/^(.*)\.([^.]+)$/)))
|
766
|
+
m = [ "", "", name ];
|
767
|
+
|
768
|
+
pkg = makePkg(m[1]);
|
769
|
+
pkg[m[2]] = componentConstructor(name);
|
770
|
+
},
|
771
|
+
|
772
|
+
setupComponents: function() {
|
773
|
+
var cmp, name, i, m, scripts=[];
|
774
|
+
|
775
|
+
d("Setting up components now.");
|
776
|
+
|
777
|
+
d("Loading scripts/ directory...");
|
778
|
+
for (name in $.golf.scripts)
|
779
|
+
scripts.push(name);
|
780
|
+
|
781
|
+
// sort scripts by name
|
782
|
+
scripts = scripts.sort();
|
783
|
+
|
784
|
+
for (i=0, m=scripts.length; i<m; i++) {
|
785
|
+
d("Evaling '"+scripts[i]+"'...");
|
786
|
+
$.globalEval($.golf.scripts[scripts[i]].js);
|
787
|
+
}
|
788
|
+
|
789
|
+
d("Loading components/ directory...");
|
790
|
+
for (name in $.golf.components)
|
791
|
+
$.golf.addComponent($.golf.components[name].html, name);
|
792
|
+
|
793
|
+
if (!window.forcebot) {
|
794
|
+
d("Loading styles/ directory...");
|
795
|
+
$("head style").remove();
|
796
|
+
for (name in $.golf.styles)
|
797
|
+
$("head").append(
|
798
|
+
"<style type='text/css'>"+$.golf.styles[name].css+"</style>");
|
799
|
+
} else {
|
800
|
+
$("head style").remove();
|
801
|
+
}
|
802
|
+
|
803
|
+
d("Done loading directories.");
|
804
|
+
},
|
805
|
+
|
806
|
+
route: function(hash, b) {
|
807
|
+
var theHash, theRoute, theAction, i, x, pat, match;
|
808
|
+
if (!hash)
|
809
|
+
hash = String($.golf.defaultRoute+"/").replace(/\/+$/, "/");
|
810
|
+
|
811
|
+
theHash = hash;
|
812
|
+
theRoute = null;
|
813
|
+
theAction = null;
|
814
|
+
|
815
|
+
if (!b) b = $("body > div.golfbody").eq(0);
|
816
|
+
b.empty();
|
817
|
+
|
818
|
+
try {
|
819
|
+
if ($.golf.controller.length > 0) {
|
820
|
+
for (i=0; i<$.golf.controller.length && theAction===null; i++) {
|
821
|
+
theRoute = "^"+$.golf.controller[i].route+"$";
|
822
|
+
match = $.isFunction(theRoute) ? theRoute(theHash)
|
823
|
+
: theHash.match(new RegExp(theRoute));
|
824
|
+
if (match)
|
825
|
+
(theAction = $.golf.controller[i].action)(b, match);
|
826
|
+
}
|
827
|
+
if (theAction === null)
|
828
|
+
$.golf.errorPage("Not Found", "<span>There is no route "
|
829
|
+
+"matching <code>"+theHash+"</code>.</span>");
|
830
|
+
} else {
|
831
|
+
$.golf.errorPage("Hi there!", "<span>Your Golf web application "
|
832
|
+
+"server is up and running.</span>");
|
833
|
+
}
|
834
|
+
} catch (e) {
|
835
|
+
$(document).trigger({
|
836
|
+
type: "route_error",
|
837
|
+
message: e.toString()
|
838
|
+
});
|
839
|
+
$.golf.errorPage("Oops!", "<code>"+e.toString()+"</code>");
|
840
|
+
}
|
841
|
+
},
|
842
|
+
|
843
|
+
errorPage: function(type, desc) {
|
844
|
+
$.get("?path=app_error.html", function(data) {
|
845
|
+
$(".golfbody").empty().append(data);
|
846
|
+
$(".golfbody .type").text(type);
|
847
|
+
$(".golfbody .description").append(desc);
|
848
|
+
});
|
849
|
+
},
|
850
|
+
|
851
|
+
require: function($fake) {
|
852
|
+
|
853
|
+
return function(name, cache) {
|
854
|
+
var js, exports, target;
|
855
|
+
|
856
|
+
try {
|
857
|
+
if (!$.golf.plugins[name])
|
858
|
+
throw "not found";
|
859
|
+
|
860
|
+
js = $.golf.plugins[name].js;
|
861
|
+
exports = {};
|
862
|
+
target = this;
|
863
|
+
|
864
|
+
if (!$.golf.singleton[name])
|
865
|
+
$.golf.singleton[name] = {};
|
866
|
+
|
867
|
+
if (cache && cache[name]) {
|
868
|
+
d("require: loading '"+name+"' recursively from cache");
|
869
|
+
return cache[name];
|
870
|
+
}
|
871
|
+
|
872
|
+
if (!cache) {
|
873
|
+
cache = {};
|
874
|
+
|
875
|
+
$fake.require = (function(orig) {
|
876
|
+
return function(name) {
|
877
|
+
return orig(name, cache);
|
878
|
+
};
|
879
|
+
})($fake.require);
|
880
|
+
}
|
881
|
+
|
882
|
+
cache[name] = exports;
|
883
|
+
|
884
|
+
(function(jQuery,$,js,singleton) {
|
885
|
+
if (!singleton._init) {
|
886
|
+
d("require: loading '"+name+"'");
|
887
|
+
eval("exports._init = function($,jQuery,exports,singleton) { "+
|
888
|
+
js+"; "+
|
889
|
+
"return exports; "+
|
890
|
+
"}");
|
891
|
+
$.extend(true, singleton, exports);
|
892
|
+
delete exports._init;
|
893
|
+
} else {
|
894
|
+
d("require: loading '"+name+"' from cache");
|
895
|
+
}
|
896
|
+
singleton._init($,$,exports,singleton);
|
897
|
+
}).call(target,$fake,$fake,js,$.golf.singleton[name]);
|
898
|
+
} catch (x) {
|
899
|
+
throw "require: "+name+".js: "+x;
|
900
|
+
}
|
901
|
+
|
902
|
+
return exports;
|
903
|
+
};
|
904
|
+
}
|
905
|
+
|
906
|
+
};
|
907
|
+
|
908
|
+
// Static jQuery methods
|
909
|
+
|
910
|
+
$.Import = function(name) {
|
911
|
+
var ret="", obj, basename, dirname, i;
|
912
|
+
|
913
|
+
basename = name.replace(/^.*\./, "");
|
914
|
+
dirname = name.replace(/\.[^.]*$/, "");
|
915
|
+
|
916
|
+
if (basename == "*") {
|
917
|
+
obj = eval(dirname);
|
918
|
+
for (i in obj)
|
919
|
+
ret += "var "+i+" = "+dirname+"['"+i+"'];";
|
920
|
+
} else {
|
921
|
+
ret = "var "+basename+" = "+name+";";
|
922
|
+
}
|
923
|
+
|
924
|
+
return ret;
|
925
|
+
};
|
926
|
+
|
927
|
+
$.require = $.golf.require($);
|
928
|
+
|
929
|
+
$.golf.location.params = function(i) {
|
930
|
+
var p = String($.golf.location.hash).replace(/(^\/|\/$)/g,"").split("/");
|
931
|
+
if (i == null)
|
932
|
+
return p;
|
933
|
+
else
|
934
|
+
return p[(p.length + i) % p.length];
|
935
|
+
};
|
936
|
+
|
937
|
+
// jQuery onload handler
|
938
|
+
|
939
|
+
$(function() {
|
940
|
+
onLoad();
|
941
|
+
});
|
942
|
+
|
943
|
+
})(jQuery);
|