www_app 1.0.0

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.
Files changed (46) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +36 -0
  3. data/Gemfile +3 -0
  4. data/LICENSE +21 -0
  5. data/README.md +84 -0
  6. data/TODO.md +13 -0
  7. data/VERSION +1 -0
  8. data/bin/www_app +46 -0
  9. data/doc/Design.md +123 -0
  10. data/doc/Why_this_arch.rb +104 -0
  11. data/lib/public/jquery-2.1.1.js +4 -0
  12. data/lib/public/jquery.serialize-object.min.js +8 -0
  13. data/lib/public/underscore-1.7.0.js +6 -0
  14. data/lib/public/underscore-min.map +1 -0
  15. data/lib/public/underscore.string-2.3.0.js +1 -0
  16. data/lib/public/www_app.js +824 -0
  17. data/lib/www_app/Clean.rb +169 -0
  18. data/lib/www_app/dsl.rb +86 -0
  19. data/lib/www_app/source.rb +53 -0
  20. data/lib/www_app.rb +1024 -0
  21. data/specs/as_ruby/0000-new.rb +23 -0
  22. data/specs/as_ruby/0010-attrs.rb +29 -0
  23. data/specs/as_ruby/0011-class.rb +39 -0
  24. data/specs/as_ruby/0011-href.rb +37 -0
  25. data/specs/as_ruby/0011-id.rb +39 -0
  26. data/specs/as_ruby/0020-tag.rb +21 -0
  27. data/specs/as_ruby/0020-tag_content.rb +43 -0
  28. data/specs/as_ruby/0021-body.rb +16 -0
  29. data/specs/as_ruby/0021-form.rb +22 -0
  30. data/specs/as_ruby/0021-link.rb +26 -0
  31. data/specs/as_ruby/0021-script.rb +44 -0
  32. data/specs/as_ruby/0030-mustache.rb +113 -0
  33. data/specs/as_ruby/0040-css.rb +174 -0
  34. data/specs/as_ruby/0050-on.rb +64 -0
  35. data/specs/client-side/index.html +90 -0
  36. data/specs/client-side/index.js +777 -0
  37. data/specs/lib/config.ru +96 -0
  38. data/specs/lib/helpers.rb +230 -0
  39. data/specs/lib/qunit/qunit-1.15.0.css +237 -0
  40. data/specs/lib/qunit/qunit-1.15.0.js +2495 -0
  41. data/specs/lib/sample.rb +23 -0
  42. data/specs/sampe.2.rb +14 -0
  43. data/specs/sample.3.rb +17 -0
  44. data/specs/sample.rb +44 -0
  45. data/www_app.gemspec +38 -0
  46. metadata +271 -0
@@ -0,0 +1,824 @@
1
+
2
+ "use strict";
3
+
4
+
5
+ var WWW_App = null;
6
+
7
+
8
+ (function () {
9
+
10
+ var VALID_TOUCH_ACTIONS = ['mousedown', 'mouseup', 'focus', 'blur', 'click'];
11
+ var all_scopes = [];
12
+ var id_counter = -1;
13
+ var INVALID_FORM_ACTION_CHARS = /[^a-z0-9\/\.\_]+/g;
14
+ var MAIN = null;
15
+ var WHITE_SPACE = /\s+/;
16
+
17
+
18
+ // ================================================================
19
+ // Helper Functions
20
+ // ================================================================
21
+
22
+ // From:
23
+ // http://stackoverflow.com/questions/1026069/capitalize-the-first-letter-of-string-in-javascript
24
+ var capitalize = function (s) {
25
+ return s.charAt(0).toUpperCase() + s.substring(1);
26
+ };
27
+
28
+
29
+ var classes = function (raw) {
30
+ return _.str.trim($(raw).attr('class')).split(WHITE_SPACE);
31
+ }; // function
32
+
33
+
34
+ var tag_name = function (raw) {
35
+ return ($(raw).prop('tagName') || '').toLowerCase();
36
+ }; // function
37
+
38
+
39
+ var inspect = function (val) {
40
+ var name = func_name(val.constructor || 'Unknown');
41
+ return name + ': ' + val;
42
+ };
43
+
44
+ var form_status = function (form, data, key) {
45
+ var dom = form.find('div.status_msg:first');
46
+ if (dom.length === 0) {
47
+ form.find('div.buttons:first').before('<div class="status_msg"></div>');
48
+ return form_status(form, data, key);
49
+ }
50
+
51
+ dom.addClass(key);
52
+ dom.html(data.clean_html[key]);
53
+ return dom;
54
+ }; // function
55
+
56
+ var form_reset_class = function (form, css_class) {
57
+ form.removeClass('submitted');
58
+ form.removeClass('loading');
59
+ form.removeClass('error');
60
+ form.removeClass('errors');
61
+
62
+ if (css_class === 'errors')
63
+ css_class = 'error';
64
+
65
+ if (css_class) {
66
+ form.addClass(css_class);
67
+ }
68
+ return form;
69
+ }; // function
70
+
71
+
72
+ var id = function (str_or_o) {
73
+ var target = $(str_or_o);
74
+ if (!target.attr('id')) {
75
+ id_counter = id_counter + 1;
76
+ target.attr('id', target.prop('tagName').toLowerCase() + '_client_default_id_' + id_counter);
77
+ }
78
+
79
+ return '#' + target.attr('id');
80
+ }; // function
81
+
82
+
83
+ var is_numeric = function (val) {
84
+ return _.isNumber(val) && !_.isNaN(val);
85
+ };
86
+
87
+
88
+ var log = function () {
89
+ if (!window.console) { return; }
90
+ return console.log.apply(console, arguments);
91
+ };
92
+
93
+
94
+ var func_name = function (raw) {
95
+ var s = null;
96
+ var name = null;
97
+
98
+ if (_.isString(raw)) {
99
+ s = raw;
100
+ } else {
101
+ s = ('' + raw);
102
+ }
103
+
104
+ name = _.last( _.first(s.split('(')).split('function ') );
105
+ return name;
106
+ };
107
+
108
+ var each = function (arr, func) {
109
+ var l = arr.length;
110
+ var i = 0;
111
+ var each_o = {
112
+
113
+ next: function () {
114
+ if (each_o.is_last()) {
115
+ throw new Error('No more items: i: ' + i + ' total: ' + l);
116
+ }
117
+ return arr[i + 1];
118
+ }, // === next
119
+
120
+ prev : function () {
121
+ if (each_o.is_first()) {
122
+ throw new Error('No previous items: i: ' + i + ' total: ' + l);
123
+ }
124
+ return arr[i - 1];
125
+ },
126
+
127
+ next_or_null: function () {
128
+ if (each_o.is_last()) { return null; }
129
+ return arr[i + 1];
130
+ },
131
+
132
+ prev_or_null : function () {
133
+ if (each_o.is_first()) { return null; }
134
+ return arr[i - 1];
135
+ },
136
+
137
+ is_first: function () {
138
+ return i < 1;
139
+ },
140
+
141
+ is_last: function () {
142
+ return i >= (l - 1);
143
+ },
144
+
145
+ grab_next: function () {
146
+ if (each_o.is_last()) {
147
+ throw new Error('Can\'t grab next because already at last position.');
148
+ }
149
+ i = i + 1;
150
+ return arr[i];
151
+ }
152
+
153
+ }; // === each_o
154
+
155
+ while ( i < l ) {
156
+ each_o.i = i;
157
+ func(arr[i], each_o);
158
+ i = i + 1;
159
+ } // while
160
+
161
+ }; // === each
162
+
163
+
164
+ var to_number_name = function (num) {
165
+ var name = null;
166
+ switch (num) {
167
+ case 0:
168
+ name = 'first';
169
+ break;
170
+
171
+ case 1:
172
+ name = 'second';
173
+ break;
174
+
175
+ case 2:
176
+ name = 'third';
177
+ break;
178
+
179
+ case 3:
180
+ name = 'fourth';
181
+ break;
182
+
183
+ case 4:
184
+ name = 'fifth';
185
+ break;
186
+
187
+ case 5:
188
+ name = 'sixth';
189
+ break;
190
+
191
+ default:
192
+ throw new Error("Unknown value: " + num);
193
+ } // === switch num
194
+ return name;
195
+ }; // function
196
+
197
+
198
+ var last_types = function (stack, types, stack_name) {
199
+ var o = {};
200
+
201
+ if (types.length === 0) {
202
+ throw new Error("No arguments.");
203
+ }
204
+
205
+ if (types.length === 1 && types[0] === 'all') {
206
+ return stack;
207
+ }
208
+
209
+ var vals = _.last(stack, types.length);
210
+
211
+ if (vals.length !== types.length) {
212
+ throw new Error('Not enough values in ' + stack_name + '.');
213
+ }
214
+
215
+ _.each(types, function (t, i) {
216
+ var val = vals[i];
217
+ var ignore_type = t === 'any' || t === 'last';
218
+
219
+ if (!ignore_type) {
220
+ if (_.isString(t)) {
221
+ throw new Error('Unknown position or type: ' + t);
222
+ }
223
+
224
+ if (val.constructor !== t) {
225
+ throw new Error('Value in ' + stack_name + " is not a " + func_name(t) + ': ' + inspect(val));
226
+ }
227
+ }
228
+
229
+ o[to_number_name(i)] = val;
230
+ });
231
+
232
+ if (types.length === 1) {
233
+ return o.first;
234
+ }
235
+
236
+ return o;
237
+ }; // last_types
238
+
239
+ // ================================================================
240
+ // === End Helper Functions =======================================
241
+ // ================================================================
242
+
243
+
244
+ // ================================================================
245
+ // Scope
246
+ // ================================================================
247
+ var Scope = function (parent) {
248
+
249
+ var o = {};
250
+ var vars = {};
251
+ var stack = [];
252
+ var events = [];
253
+ var scope_log_stack = [];
254
+ var top = o;
255
+
256
+ if (parent) {
257
+ o.parent = parent;
258
+ while(top.parent) {
259
+ top = top.parent;
260
+ }
261
+ }
262
+
263
+ all_scopes.push(o);
264
+
265
+ var scope_log = function () {
266
+ return _.each(_.toArray(arguments), function (val) {
267
+ top.log.push(val);
268
+ });
269
+ }; // function
270
+
271
+ var on = function (name, raw_target) {
272
+
273
+ if (name === 'defaults') { // =================================
274
+
275
+ // ========= Setup default actions for "button" tags: =======
276
+ _.each( $('button'), function (raw_b) {
277
+ on('click', raw_b);
278
+ }); // === _.each
279
+
280
+ // ========= Setup default actions for "a" tags: ============
281
+ _.each( $('a[href]'), function (raw_a) {
282
+ var a = $(raw_a);
283
+ var href = a.attr('href');
284
+ if (href.indexOf('#') !== 0)
285
+ return false;
286
+
287
+ var anchor = $('a[name="' + href.replace('#', '') + '"]');
288
+ if (anchor.length > 0)
289
+ return false;
290
+
291
+ on('click', a);
292
+ });
293
+
294
+ return o;
295
+ } // if 'defaults' ============================================
296
+
297
+ if (!_.contains(VALID_TOUCH_ACTIONS, name)) {
298
+ throw new Error('Unknown event name: ' + name);
299
+ }
300
+
301
+ var target = $(raw_target);
302
+ target.off(name);
303
+ target.on(name, function (e) {
304
+
305
+ e.preventDefault();
306
+ e.stopPropagation();
307
+ e.stopImmediatePropagation();
308
+
309
+ run_does(name, e.target, {event: e});
310
+
311
+ var tag = tag_name(target);
312
+ var is_click = name === 'click';
313
+ var is_a = tag === 'a';
314
+ var is_button = tag === 'button';
315
+ var is_submit = target.hasClass('submit') && target.parents('form:first').length > 0;
316
+ var is_hash = is_a && target.attr('href').indexOf('#') === 0;
317
+ var form_parents = target.parents('form');
318
+ var is_touch = _.contains(VALID_TOUCH_ACTIONS, name);
319
+
320
+ if (is_click && is_button && !is_submit ) {
321
+ _.each(classes(target), function (css) {
322
+ run_does(css, target, {event: e});
323
+ });
324
+ return false;
325
+ }
326
+
327
+ if (is_click && is_a && !is_submit && is_hash) {
328
+ var action = target.attr('href').replace('#', '');
329
+ var no_anchors = $('a[name="' + action + '"]').length === 0;
330
+ if (no_anchors)
331
+ run_does(action, target, {event: e});
332
+ return false;
333
+ }
334
+
335
+ if (is_submit) {
336
+ submit_form(e.target, {event: e});
337
+ return false;
338
+ }
339
+
340
+ if (is_touch) {
341
+ _.each(classes(target), function (css) {
342
+ run_does(css, target, {event: e});
343
+ });
344
+ }
345
+
346
+ return false;
347
+ }); // target.on
348
+
349
+ }; // === on
350
+
351
+ var click_button = function (name, raw_target, options) {
352
+ var target = $(raw_target);
353
+ var do_click = !target.hasClass('submit');
354
+
355
+ if (!do_click)
356
+ return false;
357
+
358
+ }; // function
359
+
360
+ var submit_form = function (raw_target, options) {
361
+ var e = options.event;
362
+ var target = $(raw_target);
363
+ var form = target.parents('form:first');
364
+ var tag = tag_name(target);
365
+
366
+ var form_type = _.detect('GET POST PUT DELETE'.split(/\s+/), function (val) {
367
+ return target.hasClass(val.toLowerCase());
368
+ }) || 'POST';
369
+
370
+ var form_data = form.serializeObject();
371
+ if (form_type !== 'GET' && form_type !== 'POST') {
372
+ form_data._method = form_type;
373
+ form_type = 'POST';
374
+ }
375
+
376
+ var is_success = false;
377
+ var url = form.attr('action');
378
+ var settings = {
379
+ type : form_type,
380
+ dataType : "json",
381
+ data : form_data,
382
+ success : function (data,status_str, jxhr) {
383
+ is_success = true;
384
+ if (data.clean_html.error_msg) {
385
+ form_status(form, data, 'error_msg');
386
+ form_reset_class(form, 'error');
387
+ run_does('error', target, {event: e, vars: {data: data.data}});
388
+ } else {
389
+ form_status(form, data, 'success_msg');
390
+ form_reset_class(form, 'success');
391
+ run_does('success', target, {event: e, vars: {data: data.data}});
392
+ }
393
+ },
394
+ error : function (data) {
395
+ form_status(form, {clean_html: {error_msg: 'An unknown network error has occurred.'}}, 'error_msg');
396
+ form_reset_class(form, 'error');
397
+ },
398
+ complete : function (a,b,c) {
399
+ form.removeClass('loading');
400
+ form.addClass('complete');
401
+ if (!is_success) {
402
+ form_reset_class(form, 'error');
403
+ form_status(form, 'An unknown error has occurred.');
404
+ }
405
+ }
406
+ };
407
+
408
+ var invalid = url.match(INVALID_FORM_ACTION_CHARS);
409
+ if (invalid) {
410
+ throw new Error('Invalid chars in form action url: ' + invalid.join('') );
411
+ }
412
+
413
+ form_reset_class(form, 'loading');
414
+ $.ajax(url, settings);
415
+
416
+ }; // submit_form_if_needed
417
+
418
+ var run_does = function (event_name, raw_target, options) {
419
+
420
+ var target = $(raw_target);
421
+
422
+ _.each(events, function (meta) {
423
+ var first = meta.path_tokens[0];
424
+
425
+ if (first !== event_name)
426
+ return false;
427
+
428
+ var second = meta.path_tokens[1];
429
+ var third = meta.path_tokens[2];
430
+ var relative = (third || second) ? relative_id(target, (third || second)) : null;
431
+
432
+ var is_touch = _.contains(VALID_TOUCH_ACTIONS, event_name);
433
+ var is_target = second && $(second).is(target);
434
+ var is_css = target.hasClass(event_name);
435
+ var is_href = tag_name(target) === 'a' && target.attr('href') === ('#' + event_name);
436
+ var push_target = null;
437
+
438
+ // === "/click/button.something/relative"
439
+ if (is_touch && is_target && third && relative)
440
+ push_target = relative;
441
+
442
+ else { // === "/click/button.something"
443
+ if (is_touch && is_target && !third)
444
+ push_target = id(target);
445
+
446
+ else { // === "/red/relative"
447
+ if ((is_css || is_href) && !third && relative)
448
+ push_target = relative;
449
+
450
+ else { // "/red"
451
+ if (is_css && !second && !third)
452
+ push_target = id(target);
453
+
454
+ else { // /success/#form_1
455
+ if (!third && first === event_name && relative)
456
+ push_target = relative;
457
+ }
458
+ }
459
+ }
460
+ }
461
+
462
+ if (push_target)
463
+ return child(options.vars).push(push_target).run(meta.code);
464
+
465
+ return false;
466
+ });
467
+ }; // function
468
+
469
+
470
+ // ==============================================================
471
+ // ============== stack functions ===============================
472
+ // ==============================================================
473
+
474
+ var right = function () {
475
+ return last_types(stack, _.toArray(arguments), 'stack');
476
+ };
477
+
478
+
479
+ var push = function () {
480
+ var args = _.toArray(arguments);
481
+ _.each(args, function (v) {
482
+ stack.push(v);
483
+ });
484
+ return o;
485
+ }; // push ========================================
486
+
487
+
488
+ var concat = function (arr) {
489
+ push.apply(null, arr);
490
+ return arr;
491
+ }; // concat ================================
492
+
493
+
494
+ var relative_id = function (target, selector) {
495
+ if (!selector)
496
+ throw new Error('Invalid selector: ' + selector);
497
+
498
+ var relative = $(target).find(selector)[0] || $(target).parents(selector)[0] || ($(target).is($(selector)) && target);
499
+ if (relative) {
500
+ return id(relative);
501
+ }
502
+ return null;
503
+ };
504
+
505
+ // ==============================================================
506
+ // ================ run functions ===============================
507
+ // ==============================================================
508
+
509
+ var run = function (code_array) {
510
+ each(code_array, function (item, l) {
511
+
512
+ if (_.isArray(item)) {
513
+ throw new Error("Syntax error: args w/o function name.");
514
+
515
+ } else if (_.isString(item), _.isArray(l.next_or_null())) {
516
+ run_func(item, l.grab_next());
517
+
518
+ } else {
519
+ stack.push(item);
520
+ } // === if
521
+
522
+ }); // === .each
523
+
524
+ return o;
525
+ }; // run ========================================
526
+
527
+ var run_func = function (name, raw_args) {
528
+
529
+ var compiled_args = null;
530
+ var first = null;
531
+ var second = null;
532
+ var left_args = null;
533
+ var target = null;
534
+
535
+ var run_args = function () {
536
+ if (!compiled_args) {
537
+ compiled_args = child().run(raw_args).right('all');
538
+ }
539
+
540
+ return compiled_args;
541
+ }; // run_args
542
+
543
+ var left = function () {
544
+ return last_types(run_args(), _.toArray(arguments), 'args');
545
+ };
546
+
547
+ var replace_left = function (arr) {
548
+ compiled_args = arr;
549
+ return compiled_args;
550
+ };
551
+
552
+ switch (name) {
553
+
554
+ case 'get':
555
+ return push(get(left(String)));
556
+
557
+ case 'focus on ancestor':
558
+ set('the focus', the_focus().parents(left(String)));
559
+ return get('the focus');
560
+
561
+ case 'submit':
562
+ var form = the_focus();
563
+ var action = form.attr('action');
564
+ if (/[^a-zA-Z0-9\_\-\/]+/.test(action)) {
565
+ throw new Error("Invalid chars in #" + form.attr('id') + " action: " + action);
566
+ }
567
+ return null;
568
+
569
+ case 'array':
570
+ push(run_args());
571
+ return right('last');
572
+
573
+ case 'remove class':
574
+ the_focus().removeClass(left(String));
575
+ return left('last');
576
+
577
+ case 'add class':
578
+ the_focus().addClass(left(String));
579
+ return left('last');
580
+
581
+ case 'add to stack':
582
+ concat( run_args() );
583
+ return run_args();
584
+
585
+ case "and":
586
+ first = right(Boolean);
587
+ second = null;
588
+ left_args = null;
589
+
590
+ if (first === true) {
591
+ second = left(Boolean);
592
+
593
+ if (first === true && second === true) {
594
+ push(true);
595
+ return true;
596
+ }
597
+ }
598
+
599
+ push(false);
600
+ return false;
601
+
602
+ case "or":
603
+ first = right(Boolean);
604
+ second = null;
605
+ left_args = null;
606
+
607
+ if (first === true) {
608
+ push(true);
609
+ return true;
610
+ }
611
+
612
+ second = left(Boolean);
613
+
614
+ if (second === true) {
615
+ push(true);
616
+ return true;
617
+ }
618
+
619
+ push(false);
620
+ return false;
621
+
622
+ case "if true":
623
+ first = right(Boolean);
624
+
625
+ if (first) {
626
+ run_args();
627
+ }
628
+
629
+ return null;
630
+
631
+ case "if false":
632
+ first = right(Boolean);
633
+
634
+ if (!first) {
635
+ run_args();
636
+ }
637
+
638
+ return null;
639
+
640
+ case 'log':
641
+ scope_log.apply(null, run_args());
642
+ return run_args();
643
+
644
+ case "on click":
645
+ var focus_selector = get('the focus');
646
+ var scope = child();
647
+ scope.set('the focus', focus_selector);
648
+
649
+ $(focus_selector).click(function () {
650
+ scope.run(raw_args);
651
+ });
652
+
653
+ return null;
654
+
655
+ case "on":
656
+ throw new Error('Not ready yet: on');
657
+
658
+ case 'bigger or equal':
659
+ return run_func('compare numbers', ['>=', left(Number)]);
660
+
661
+ case 'bigger':
662
+ return run_func('compare numbers', ['>', left(Number)]);
663
+
664
+ case 'less':
665
+ return run_func('compare numbers', ['<', left(Number)]);
666
+
667
+ case 'less or equal':
668
+ return run_func('compare numbers', ['<=', left(Number)]);
669
+
670
+ case 'equal':
671
+ first = right('any');
672
+ second = left('any');
673
+ push(first === second);
674
+ return right('last');
675
+
676
+ case 'compare numbers':
677
+ first = right(Number);
678
+
679
+ var args = left(String, Number);
680
+ var compare = args.first;
681
+ second = args.second;
682
+
683
+ var result = null;
684
+
685
+ switch (compare) {
686
+
687
+ case '===':
688
+ result = first === second;
689
+ break;
690
+
691
+ case '<=':
692
+ result = first <= second;
693
+ break;
694
+
695
+ case '<':
696
+ result = first < second;
697
+ break;
698
+
699
+ case '>=':
700
+ result = first >= second;
701
+ break;
702
+
703
+ case '>':
704
+ result = first > second;
705
+ break;
706
+
707
+ default:
708
+ throw new Error("Unknown value : " + compare);
709
+ } // === switch
710
+
711
+ push(result);
712
+ return result;
713
+
714
+ case 'allows':
715
+ var event_name = left(String);
716
+ target = $(right(String));
717
+
718
+ on(event_name, target);
719
+ return event_name;
720
+
721
+ case 'does':
722
+ var path = right(String);
723
+
724
+ var meta = {};
725
+ meta.path_tokens = _.map(path.split('/'), function (v) {
726
+ return _.str.trim(v);
727
+ });
728
+
729
+ if (meta.path_tokens[0] === '') {
730
+ meta.path_tokens.shift();
731
+ }
732
+
733
+ if (meta.path_tokens.length < 1 || meta.path_tokens.length > 3) {
734
+ throw new Error('Unknown path: ' + path);
735
+ }
736
+
737
+ events.push({
738
+ code : raw_args,
739
+ path : path,
740
+ path_tokens : meta.path_tokens
741
+ });
742
+
743
+ return path;
744
+
745
+ case 'remove':
746
+ $(right(String)).find(left(String)).remove();
747
+ return null;
748
+
749
+
750
+ default:
751
+ throw new Error("Function not found: " + name);
752
+ } // === switch name
753
+
754
+ }; // run_func ===================================
755
+
756
+
757
+ // ==============================================================
758
+ // ============= miscel. functions ==============================
759
+ // ==============================================================
760
+
761
+ var child = function (vars) {
762
+ var s = new Scope(o);
763
+ if (vars) {
764
+ _.each(vars, function (val, key) {
765
+ s.set(key, val);
766
+ });
767
+ }
768
+ return( s );
769
+ };
770
+
771
+ var the_focus = function () {
772
+ return $(right(String));
773
+ };
774
+
775
+ var set = function (name, val) {
776
+ vars[name] = val;
777
+ return val;
778
+ }; // function
779
+
780
+ var get = function (name) {
781
+ if (!vars.hasOwnProperty(name) && !parent) {
782
+ throw new Error('No var found with name: ' + name);
783
+ }
784
+
785
+ return (vars.hasOwnProperty(name)) ?
786
+ vars[name] :
787
+ parent.get(name);
788
+ }; // val =========================================
789
+
790
+
791
+ o.run = run;
792
+
793
+ // ====================================================
794
+ // The following functions
795
+ // are meant to be used by WWW_App.run.
796
+ // Don't use them.
797
+ // ====================================================
798
+ o.right = right;
799
+ o.get = get;
800
+ o.set = set;
801
+ o.push = push;
802
+ o.on = on;
803
+ o.log = scope_log_stack;
804
+ // ====================================================
805
+
806
+ return o;
807
+
808
+ // ================================================================
809
+ }; // ===== Scope =================================================
810
+ // ================================================================
811
+
812
+ WWW_App = {
813
+ run : function (code_array) {
814
+ WWW_App.MAIN = (new Scope()).on('defaults').run(code_array);
815
+ return WWW_App.MAIN;
816
+ }
817
+ };
818
+
819
+ WWW_App.run([]);
820
+
821
+ })(); // === WWW_App scope
822
+
823
+
824
+