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.
- checksums.yaml +7 -0
- data/.gitignore +36 -0
- data/Gemfile +3 -0
- data/LICENSE +21 -0
- data/README.md +84 -0
- data/TODO.md +13 -0
- data/VERSION +1 -0
- data/bin/www_app +46 -0
- data/doc/Design.md +123 -0
- data/doc/Why_this_arch.rb +104 -0
- data/lib/public/jquery-2.1.1.js +4 -0
- data/lib/public/jquery.serialize-object.min.js +8 -0
- data/lib/public/underscore-1.7.0.js +6 -0
- data/lib/public/underscore-min.map +1 -0
- data/lib/public/underscore.string-2.3.0.js +1 -0
- data/lib/public/www_app.js +824 -0
- data/lib/www_app/Clean.rb +169 -0
- data/lib/www_app/dsl.rb +86 -0
- data/lib/www_app/source.rb +53 -0
- data/lib/www_app.rb +1024 -0
- data/specs/as_ruby/0000-new.rb +23 -0
- data/specs/as_ruby/0010-attrs.rb +29 -0
- data/specs/as_ruby/0011-class.rb +39 -0
- data/specs/as_ruby/0011-href.rb +37 -0
- data/specs/as_ruby/0011-id.rb +39 -0
- data/specs/as_ruby/0020-tag.rb +21 -0
- data/specs/as_ruby/0020-tag_content.rb +43 -0
- data/specs/as_ruby/0021-body.rb +16 -0
- data/specs/as_ruby/0021-form.rb +22 -0
- data/specs/as_ruby/0021-link.rb +26 -0
- data/specs/as_ruby/0021-script.rb +44 -0
- data/specs/as_ruby/0030-mustache.rb +113 -0
- data/specs/as_ruby/0040-css.rb +174 -0
- data/specs/as_ruby/0050-on.rb +64 -0
- data/specs/client-side/index.html +90 -0
- data/specs/client-side/index.js +777 -0
- data/specs/lib/config.ru +96 -0
- data/specs/lib/helpers.rb +230 -0
- data/specs/lib/qunit/qunit-1.15.0.css +237 -0
- data/specs/lib/qunit/qunit-1.15.0.js +2495 -0
- data/specs/lib/sample.rb +23 -0
- data/specs/sampe.2.rb +14 -0
- data/specs/sample.3.rb +17 -0
- data/specs/sample.rb +44 -0
- data/www_app.gemspec +38 -0
- 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
|
+
|