Skip to content

Commit 68d3986

Browse files
committed
Fixed parsing of expression that has property operations
Improved App, Expression and Selector classes tests Some reworking of main evente object Status icons changed using badgen.net
1 parent 6826d7b commit 68d3986

8 files changed

Lines changed: 155 additions & 88 deletions

File tree

README.md

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
1-
[![Maintainability](https://api.codeclimate.com/v1/badges/6b8b7666060ce232cca8/maintainability)](https://codeclimate.com/github/evnte/core/maintainability)
2-
[![Test Coverage](https://api.codeclimate.com/v1/badges/6b8b7666060ce232cca8/test_coverage)](https://codeclimate.com/github/evente/core/test_coverage)
3-
[![Build Status](https://travis-ci.org/evente/core.svg?branch=master)](https://travis-ci.org/evente/core)
1+
[![Maintainability](https://badgen.net/codeclimate/maintainability/evente/core)](https://codeclimate.com/github/evnte/core/maintainability)
2+
[![Test Coverage](https://badgen.net/codeclimate/coverage/evente/core)](https://codeclimate.com/github/evente/core/test_coverage)
3+
[![Build Status](https://badgen.net/travis/evente/core)](https://travis-ci.org/evente/core)
4+
![Size](https://badgen.net/badgesize/normal/evente/core/master/dist/evente.min.js)
5+
![GZip Size](https://badgen.net/badgesize/gzip/evente/core/master/dist/evente.min.js)
46

5-
`Evente` - javascript library for building reactive web applications. Library is suitable for writing web applications from scratch and also for using in existing applications. And it is very small - `21k minified` and `6.2k gzipped` so it cause very low impact on the time of application loading.
7+
`Evente` - javascript library for building reactive web applications. Library is suitable for writing web applications from scratch and also for using in existing applications. Its size is very small and cause low impact on the loading time.
68

79
# Features
810
- `jQuery`-like objects with subset of well known methods: `addClass`, `attr`, `closest`, `contains`, `end`, `find`, `get`, `hasClass`, `html`, `is`, `parent`, `removeClass`, `text`, `toggleClass`, `val`
911
- Custom listeners for `get`, `set` or `delete` operations with model properties
1012
- Two way data binding
1113
- Expressions with pipes for output modifications
12-
- Working with HTTP resources using `fetch` and `promise`s
14+
- Working with HTTP resources using `fetch` and `promise`
1315
- Routing
1416

1517
# Getting started

dist/evente.js

Lines changed: 25 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,13 @@ Object.defineProperty(
3838
}
3939
}
4040
);
41-
var evente = function(selector) {
42-
return new evente.Selector(selector);
43-
}
41+
var evente = function() {}
4442

4543
evente.attributes = {};
4644
evente.models = [];
4745
evente.routers = [];
4846
evente.strings = [];
47+
4948
evente.pipes = {
5049
empty: function(params) {
5150
return params[0] === undefined || params[0] === null ? ( params[1] ? params[1] : '' ) : ( params[2] ? params[2] : '' );
@@ -124,15 +123,13 @@ evente.__proto__.route = function() {
124123
evente.routers[i].handle(location.href);
125124
}
126125

127-
if ( typeof module !== 'undefined' ) {
126+
if ( typeof $ === 'undefined' )
127+
var $ = function(selector) { return new evente.Selector(selector); }
128+
129+
if ( typeof module !== 'undefined' )
128130
module.exports = evente;
129-
} else {
130-
if ( typeof e === 'undefined' )
131-
var e = evente;
132-
if ( typeof $ === 'undefined' )
133-
var $ = evente;
131+
else
134132
window.addEventListener('popstate', evente.route);
135-
}
136133

137134
evente.Expression = class {
138135

@@ -192,7 +189,7 @@ evente.Expression = class {
192189
case 'value':
193190
value = this[property ? 'property' : 'eval'](model, item.params[0]);
194191
break;
195-
case 'property':
192+
case '.':
196193
if ( property ) {
197194
value = this.property(model, item.params[0]);
198195
value = value !== undefined ? value + '.' + item.params[1] : undefined;
@@ -201,12 +198,12 @@ evente.Expression = class {
201198
value = value !== undefined ? value.getField(item.params[1]) : undefined;
202199
}
203200
break;
204-
case 'index':
201+
case '[]':
205202
value = item.params[0] + '.' + this.eval(model, item.params[1]);
206203
if ( !property )
207204
value = model.get(value);
208205
break;
209-
case 'pipe':
206+
case '|':
210207
let params = [];
211208
for ( let i in item.params )
212209
params.push( this.eval(model, item.params[i] ) );
@@ -237,7 +234,7 @@ evente.Expression = class {
237234
break;
238235
default:
239236
switch ( item.type ) {
240-
case 'property':
237+
case '.':
241238
links.push(...this.getLinks(item.params[0]));
242239
break;
243240
default:
@@ -381,7 +378,7 @@ evente.Expression = class {
381378
break;
382379
if ( evente.Expression.operations[item.type].priority >= evente.Expression.operations[token].priority )
383380
item = { type: token, params: [ item ] };
384-
if ( evente.Expression.operations[item.type].priority < evente.Expression.operations[token].priority )
381+
else
385382
item.params.push(this.parse_tree(
386383
tokens,
387384
{ type: token, params: [ item.params.pop() ] }
@@ -396,10 +393,10 @@ evente.Expression = class {
396393
return item;
397394
case '[':
398395
if ( item.type === undefined ) {
399-
item.type = 'index';
396+
item.type = '[]';
400397
item.params.push(this.parse_tree(tokens));
401398
} else
402-
item.params.push( { type: 'index', params: [ item.params.pop(), this.parse_tree(tokens) ] } );
399+
item.params.push( { type: '[]', params: [ item.params.pop(), this.parse_tree(tokens) ] } );
403400
break;
404401
case ']':
405402
if ( item.type === undefined )
@@ -408,7 +405,7 @@ evente.Expression = class {
408405
case '|':
409406
if ( item.type !== undefined )
410407
item = { params: [ item ] };
411-
item.type = 'pipe';
408+
item.type = '|';
412409
item.name = tokens.shift();
413410
token = tokens.shift();
414411
while ( token === ':' ) {
@@ -429,10 +426,14 @@ evente.Expression = class {
429426
if ( token[0] == '.' ) {
430427
token = token.substr(1);
431428
if ( item.type === undefined ) {
432-
item.type = 'property';
429+
item.type = '.';
433430
item.params.push(token);
434-
} else
435-
item = {type: 'property', params: [item, token]};
431+
} else {
432+
if ( evente.Expression.operations[item.type].priority >= evente.Expression.operations['.'].priority )
433+
item = {type: '.', params: [item, token]};
434+
else
435+
item.params.push({type: '.', params: [item.params.pop(), token]});
436+
}
436437
} else {
437438
tmp = parseFloat(token);
438439
if ( !isNaN(tmp) )
@@ -458,8 +459,9 @@ evente.Expression.operations = {
458459
'=': { priority: 3, func: function(a, b) { return Boolean(a == b); } },
459460
'#': { priority: 3, func: function(a, b) { return Boolean(a != b); } },
460461
'!': { priority: 4 },
461-
'property': { priority: 5 },
462-
'pipe': { priority: 6 },
462+
'.': { priority: 5 },
463+
'[]': { priority: 6 },
464+
'|': { priority: 7 },
463465
};
464466

465467
evente.Attribute = class extends evente.Expression {

dist/evente.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Expression.js

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ evente.Expression = class {
5858
case 'value':
5959
value = this[property ? 'property' : 'eval'](model, item.params[0]);
6060
break;
61-
case 'property':
61+
case '.':
6262
if ( property ) {
6363
value = this.property(model, item.params[0]);
6464
value = value !== undefined ? value + '.' + item.params[1] : undefined;
@@ -67,12 +67,12 @@ evente.Expression = class {
6767
value = value !== undefined ? value.getField(item.params[1]) : undefined;
6868
}
6969
break;
70-
case 'index':
70+
case '[]':
7171
value = item.params[0] + '.' + this.eval(model, item.params[1]);
7272
if ( !property )
7373
value = model.get(value);
7474
break;
75-
case 'pipe':
75+
case '|':
7676
let params = [];
7777
for ( let i in item.params )
7878
params.push( this.eval(model, item.params[i] ) );
@@ -103,7 +103,7 @@ evente.Expression = class {
103103
break;
104104
default:
105105
switch ( item.type ) {
106-
case 'property':
106+
case '.':
107107
links.push(...this.getLinks(item.params[0]));
108108
break;
109109
default:
@@ -247,7 +247,7 @@ evente.Expression = class {
247247
break;
248248
if ( evente.Expression.operations[item.type].priority >= evente.Expression.operations[token].priority )
249249
item = { type: token, params: [ item ] };
250-
if ( evente.Expression.operations[item.type].priority < evente.Expression.operations[token].priority )
250+
else
251251
item.params.push(this.parse_tree(
252252
tokens,
253253
{ type: token, params: [ item.params.pop() ] }
@@ -262,10 +262,10 @@ evente.Expression = class {
262262
return item;
263263
case '[':
264264
if ( item.type === undefined ) {
265-
item.type = 'index';
265+
item.type = '[]';
266266
item.params.push(this.parse_tree(tokens));
267267
} else
268-
item.params.push( { type: 'index', params: [ item.params.pop(), this.parse_tree(tokens) ] } );
268+
item.params.push( { type: '[]', params: [ item.params.pop(), this.parse_tree(tokens) ] } );
269269
break;
270270
case ']':
271271
if ( item.type === undefined )
@@ -274,7 +274,7 @@ evente.Expression = class {
274274
case '|':
275275
if ( item.type !== undefined )
276276
item = { params: [ item ] };
277-
item.type = 'pipe';
277+
item.type = '|';
278278
item.name = tokens.shift();
279279
token = tokens.shift();
280280
while ( token === ':' ) {
@@ -295,10 +295,14 @@ evente.Expression = class {
295295
if ( token[0] == '.' ) {
296296
token = token.substr(1);
297297
if ( item.type === undefined ) {
298-
item.type = 'property';
298+
item.type = '.';
299299
item.params.push(token);
300-
} else
301-
item = {type: 'property', params: [item, token]};
300+
} else {
301+
if ( evente.Expression.operations[item.type].priority >= evente.Expression.operations['.'].priority )
302+
item = {type: '.', params: [item, token]};
303+
else
304+
item.params.push({type: '.', params: [item.params.pop(), token]});
305+
}
302306
} else {
303307
tmp = parseFloat(token);
304308
if ( !isNaN(tmp) )
@@ -324,6 +328,7 @@ evente.Expression.operations = {
324328
'=': { priority: 3, func: function(a, b) { return Boolean(a == b); } },
325329
'#': { priority: 3, func: function(a, b) { return Boolean(a != b); } },
326330
'!': { priority: 4 },
327-
'property': { priority: 5 },
328-
'pipe': { priority: 6 },
331+
'.': { priority: 5 },
332+
'[]': { priority: 6 },
333+
'|': { priority: 7 },
329334
};

src/evente.js

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
1-
var evente = function(selector) {
2-
return new evente.Selector(selector);
3-
}
1+
var evente = function() {}
42

53
evente.attributes = {};
64
evente.models = [];
75
evente.routers = [];
86
evente.strings = [];
7+
98
evente.pipes = {
109
empty: function(params) {
1110
return params[0] === undefined || params[0] === null ? ( params[1] ? params[1] : '' ) : ( params[2] ? params[2] : '' );
@@ -84,12 +83,10 @@ evente.__proto__.route = function() {
8483
evente.routers[i].handle(location.href);
8584
}
8685

87-
if ( typeof module !== 'undefined' ) {
86+
if ( typeof $ === 'undefined' )
87+
var $ = function(selector) { return new evente.Selector(selector); }
88+
89+
if ( typeof module !== 'undefined' )
8890
module.exports = evente;
89-
} else {
90-
if ( typeof e === 'undefined' )
91-
var e = evente;
92-
if ( typeof $ === 'undefined' )
93-
var $ = evente;
91+
else
9492
window.addEventListener('popstate', evente.route);
95-
}

test/App.js

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,47 @@ var evente = require('../scripts/test.js');
22

33
describe('App class', () => {
44

5-
document.body.innerHTML =
6-
'<div data-model="text"></div>';
5+
html =
6+
'<!-- Comment -->' +
7+
' ' +
8+
'<div id="div" e-model="text"></div>' +
9+
'{{ text }}';
10+
document.body.innerHTML = html;
711

812
test('App object creation', () => {
913
let app = new evente.App('body');
1014
expect(app.model.selector).toHaveLength(1);
1115
});
1216

17+
test('Removing comments and empty text nodes', () => {
18+
let app = new evente.App('body', {}, {run: true});
19+
expect(document.body.childNodes).toHaveLength(2);
20+
});
21+
22+
test('Get model data', () => {
23+
let app = new evente.App('body', {text: 'text'}, {run: true});
24+
expect(app.data.text).toBe('text');
25+
});
26+
27+
test('Set model data', () => {
28+
document.body.innerHTML = html;
29+
let app = new evente.App('body', {}, {run: true});
30+
app.data = {text: 'text'};
31+
expect(document.getElementById('div').textContent).toBe('text');
32+
});
33+
1334
test('Add route', () => {
1435
let app = new evente.App('body');
1536
app.route('/test/', options => {});
1637
expect(Object.keys(app.router.routes)).toHaveLength(1);
1738
});
1839

40+
test('Add route with disabled routing', () => {
41+
let app = new evente.App('body', {}, {router: false});
42+
app.route('/test/', options => {});
43+
expect(app.router).toBeUndefined();
44+
});
45+
1946
test('Remove route', () => {
2047
let app = new evente.App('body');
2148
app.route('/', options => {});

test/Expression.js

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ html_expression =
44
'<div id="simple">{{ 2 * a + b - c }} = 1</div>' +
55
'<div id="brackets">{{ 2 * (a + b) - c / 2 }}</div>' +
66
'<div id="booleans">{{ ( a || b ) && c && !d }}</div>' +
7-
'<div id="index">{{ items[id + 1].name }}</div>' +
7+
'<div id="index_property">{{ items[id + 1].name }}</div>' +
8+
'<div id="add_index_property">{{ "name: " + items[id + 1].name }}</div>' +
89
'<div id="filter_if">{{ a == b | if:a + " is equal " + b }}</div>' +
910
'<div id="filter_min_max">{{ numbers | min }}...{{ numbers | max }}</div>' +
1011
'';
@@ -33,7 +34,13 @@ describe('Expression class', () => {
3334
test('Index and property', () => {
3435
document.body.innerHTML = html_expression;
3536
let model = new evente.Model('body', {id: 0, items: {1: {name: "one"}}});
36-
expect(document.getElementById('index').innerHTML).toBe("one");
37+
expect(document.getElementById('index_property').innerHTML).toBe("one");
38+
});
39+
40+
test('Adding with index and property', () => {
41+
document.body.innerHTML = html_expression;
42+
let model = new evente.Model('body', {id: 0, items: {1: {name: "one"}}});
43+
expect(document.getElementById('add_index_property').innerHTML).toBe("name: one");
3744
});
3845

3946
test('Filter if', () => {

0 commit comments

Comments
 (0)