golf 0.0.4 → 0.0.5

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