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.
@@ -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);