golf 0.0.8 → 0.0.9

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+ "&amp;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, "&amp;")
733
+ .replace(/</g, "&lt;")
734
+ .replace(/>/g, "&gt;")
735
+ .replace(/"/g, "&quot;");
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);