simplyview 1.0.0 → 2.0.2

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 (49) hide show
  1. package/README.md +9 -6
  2. package/dist/simply.everything.js +1596 -1139
  3. package/docs/examples.md +82 -0
  4. package/docs/readme.md +33 -0
  5. package/docs/simply.action.md +42 -0
  6. package/docs/simply.activate.md +27 -0
  7. package/docs/simply.api.md +188 -0
  8. package/docs/simply.app.md +27 -0
  9. package/docs/simply.collect.md +64 -0
  10. package/docs/simply.command.md +110 -0
  11. package/docs/simply.include.md +61 -0
  12. package/docs/simply.keyboard.md +60 -0
  13. package/docs/simply.path.md +3 -0
  14. package/docs/simply.route.md +133 -0
  15. package/docs/simply.view.md +53 -0
  16. package/docs/simply.viewmodel.md +3 -0
  17. package/examples/counter.html +1 -0
  18. package/examples/github.html +39 -0
  19. package/examples/githubv4.html +107 -0
  20. package/examples/graphql.html +51 -0
  21. package/examples/graphql.html~ +35 -0
  22. package/examples/keyboard.html +41 -0
  23. package/examples/viewmodel.html +359 -0
  24. package/js/simply.action.js +14 -5
  25. package/js/simply.activate.js +12 -4
  26. package/js/simply.api.js +229 -0
  27. package/js/simply.app.js +27 -9
  28. package/js/simply.collect.js +13 -5
  29. package/js/simply.command.js +36 -6
  30. package/js/simply.include.js +38 -17
  31. package/js/simply.keyboard.js +45 -0
  32. package/js/simply.modules.js +22 -0
  33. package/js/simply.observe.js +13 -4
  34. package/js/simply.path.js +12 -4
  35. package/js/simply.render.js +12 -6
  36. package/js/simply.resize.js +28 -20
  37. package/js/simply.route.js +149 -19
  38. package/js/simply.view.js +16 -9
  39. package/js/simply.viewmodel.js +174 -0
  40. package/make +16 -2
  41. package/make~ +17 -0
  42. package/package.json +6 -3
  43. package/package.json~ +8 -5
  44. package/test/simply.route.test.js +102 -0
  45. package/examples/todo.html~ +0 -50
  46. package/js/simply.app.js~ +0 -44
  47. package/js/simply.bind.js +0 -253
  48. package/js/simply.command.js~ +0 -166
  49. package/js/simply.resize.js~ +0 -69
@@ -1,6 +1,17 @@
1
- this.simply = (function(simply, global) {
1
+ (function(global) {
2
+ 'use strict';
2
3
 
3
4
  var routeInfo = [];
5
+ var listeners = {
6
+ goto: {},
7
+ match: {},
8
+ call: {},
9
+ finish: {}
10
+ };
11
+
12
+ function getRegexpFromRoute(route) {
13
+ return new RegExp('^'+route.replace(/:\w+/g, '([^/]+)').replace(/:\*/, '(.*)'));
14
+ }
4
15
 
5
16
  function parseRoutes(routes) {
6
17
  var paths = Object.keys(routes);
@@ -17,7 +28,7 @@ this.simply = (function(simply, global) {
17
28
  }
18
29
  } while(matches);
19
30
  routeInfo.push({
20
- match: new RegExp(path.replace(/:\w+/g, '([^/]+)').replace(/:\*/, '(.*)')),
31
+ match: getRegexpFromRoute(path),
21
32
  params: params,
22
33
  action: routes[path]
23
34
  });
@@ -37,35 +48,115 @@ this.simply = (function(simply, global) {
37
48
  }
38
49
  if (link
39
50
  && link.pathname
40
- && link.hostname==document.location.hostname
51
+ && link.hostname==global.location.hostname
41
52
  && !link.link
42
53
  && !link.dataset.simplyCommand
43
- && simply.route.has(link.pathname)
44
54
  ) {
45
- simply.route.goto(link.pathname);
46
- evt.preventDefault();
47
- return false;
55
+ let path = getPath(link.pathname+link.hash);
56
+ if ( !route.has(path) ) {
57
+ path = getPath(link.pathname);
58
+ }
59
+ if ( route.has(path) ) {
60
+ let params = runListeners('goto', { path: path});
61
+ if (params.path) {
62
+ route.goto(params.path);
63
+ }
64
+ evt.preventDefault();
65
+ return false;
66
+ }
48
67
  }
49
68
  };
50
69
 
51
- simply.route = {
70
+ var options = {
71
+ root: '/'
72
+ };
73
+
74
+ var getPath = function(path) {
75
+ if (path.substring(0,options.root.length)==options.root
76
+ ||
77
+ ( options.root[options.root.length-1]=='/'
78
+ && path.length==(options.root.length-1)
79
+ && path == options.root.substring(0,path.length)
80
+ )
81
+ ) {
82
+ path = path.substring(options.root.length);
83
+ }
84
+ if (path[0]!='/' && path[0]!='#') {
85
+ path = '/'+path;
86
+ }
87
+ return path;
88
+ };
89
+
90
+ var getUrl = function(path) {
91
+ path = getPath(path);
92
+ if (options.root[options.root.length-1]==='/' && path[0]==='/') {
93
+ path = path.substring(1);
94
+ }
95
+ return options.root + path;
96
+ };
97
+
98
+ function runListeners(action, params) {
99
+ if (!Object.keys(listeners[action])) {
100
+ return;
101
+ }
102
+ Object.keys(listeners[action]).forEach(function(route) {
103
+ var routeRe = getRegexpFromRoute(route);
104
+ if (routeRe.exec(params.path)) {
105
+ var result;
106
+ listeners[action][route].forEach(function(callback) {
107
+ result = callback.call(global, params);
108
+ if (result) {
109
+ params = result;
110
+ }
111
+ });
112
+ }
113
+ });
114
+ return params;
115
+ }
116
+
117
+ var route = {
52
118
  handleEvents: function() {
53
119
  global.addEventListener('popstate', function() {
54
- simply.route.match(document.location.pathname);
120
+ if (route.match(getPath(document.location.pathname + document.location.hash)) === false) {
121
+ route.match(getPath(document.location.pathname));
122
+ }
55
123
  });
56
- document.addEventListener('click', linkHandler);
124
+ global.document.addEventListener('click', linkHandler);
57
125
  },
58
126
  load: function(routes) {
59
127
  parseRoutes(routes);
60
128
  },
129
+ clear: function() {
130
+ routeInfo = [];
131
+ listeners = {
132
+ match: {},
133
+ call: {},
134
+ finish: {}
135
+ };
136
+ },
61
137
  match: function(path, options) {
138
+ var args = {
139
+ path: path,
140
+ options: options
141
+ };
142
+ args = runListeners('match',args);
143
+ path = args.path ? args.path : path;
144
+
62
145
  var matches;
146
+ if (!path) {
147
+ if (route.match(document.location.pathname+document.location.hash)) {
148
+ return true;
149
+ } else {
150
+ return route.match(document.location.pathname);
151
+ }
152
+ }
153
+ path = getPath(path);
63
154
  for ( var i=0; i<routeInfo.length; i++) {
64
- if (path[path.length-1]!='/') {
155
+ if (path && path[path.length-1]!='/') {
65
156
  matches = routeInfo[i].match.exec(path+'/');
66
157
  if (matches) {
67
158
  path+='/';
68
- history.replaceState({}, '', path);
159
+ history.replaceState({}, '', getUrl(path));
69
160
  }
70
161
  }
71
162
  matches = routeInfo[i].match.exec(path);
@@ -78,15 +169,23 @@ this.simply = (function(simply, global) {
78
169
  params[key] = matches[i+1];
79
170
  });
80
171
  Object.assign(params, options);
81
- return routeInfo[i].action.call(simply.route, params);
82
- }
172
+ args.route = route;
173
+ args.params = params;
174
+ args = runListeners('call', args);
175
+ params = args.params ? args.params : params;
176
+ args.result = routeInfo[i].action.call(route, params);
177
+ runListeners('finish', args);
178
+ return args.result;
179
+ }
83
180
  }
181
+ return false;
84
182
  },
85
183
  goto: function(path) {
86
- history.pushState({},'',path);
87
- return simply.route.match(path);
184
+ history.pushState({},'',getUrl(path));
185
+ return route.match(path);
88
186
  },
89
187
  has: function(path) {
188
+ path = getPath(path);
90
189
  for ( var i=0; i<routeInfo.length; i++) {
91
190
  var matches = routeInfo[i].match.exec(path);
92
191
  if (matches && matches.length) {
@@ -94,9 +193,40 @@ this.simply = (function(simply, global) {
94
193
  }
95
194
  }
96
195
  return false;
196
+ },
197
+ addListener: function(action, route, callback) {
198
+ if (['goto','match','call','finish'].indexOf(action)==-1) {
199
+ throw new Error('Unknown action '+action);
200
+ }
201
+ if (!listeners[action][route]) {
202
+ listeners[action][route] = [];
203
+ }
204
+ listeners[action][route].push(callback);
205
+ },
206
+ removeListener: function(action, route, callback) {
207
+ if (['match','call','finish'].indexOf(action)==-1) {
208
+ throw new Error('Unknown action '+action);
209
+ }
210
+ if (!listeners[action][route]) {
211
+ return;
212
+ }
213
+ listeners[action][route] = listeners[action][route].filter(function(listener) {
214
+ return listener != callback;
215
+ });
216
+ },
217
+ init: function(params) {
218
+ if (params.root) {
219
+ options.root = params.root;
220
+ }
97
221
  }
98
222
  };
99
223
 
100
- return simply;
101
-
102
- })(this.simply || {}, this);
224
+ if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') {
225
+ module.exports = route;
226
+ } else {
227
+ if (!global.simply) {
228
+ global.simply = {};
229
+ }
230
+ global.simply.route = route;
231
+ }
232
+ })(this);
package/js/simply.view.js CHANGED
@@ -1,22 +1,22 @@
1
- this.simply = (function(simply, global) {
2
-
3
- simply.view = function(app, view) {
1
+ (function(global) {
2
+ 'use strict';
3
+ var view = function(app, view) {
4
4
 
5
5
  app.view = view || {};
6
6
 
7
7
  var load = function() {
8
8
  var data = app.view;
9
- var path = editor.data.getDataPath(app.container);
10
- app.view = editor.currentData[path];
9
+ var path = global.editor.data.getDataPath(app.container);
10
+ app.view = global.editor.currentData[path];
11
11
  Object.keys(data).forEach(function(key) {
12
12
  app.view[key] = data[key];
13
13
  });
14
14
  };
15
15
 
16
- if (global.editor && editor.currentData) {
16
+ if (global.editor && global.editor.currentData) {
17
17
  load();
18
18
  } else {
19
- document.addEventListener('simply-content-loaded', function() {
19
+ global.document.addEventListener('simply-content-loaded', function() {
20
20
  load();
21
21
  });
22
22
  }
@@ -24,5 +24,12 @@ this.simply = (function(simply, global) {
24
24
  return app.view;
25
25
  };
26
26
 
27
- return simply;
28
- })(this.simply || {}, this);
27
+ if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') {
28
+ module.exports = view;
29
+ } else {
30
+ if (!global.simply) {
31
+ global.simply = {};
32
+ }
33
+ global.simply.view = view;
34
+ }
35
+ })(this);
@@ -0,0 +1,174 @@
1
+ (function(global) {
2
+ 'use strict';
3
+
4
+ function ViewModel(name, data, options) {
5
+ this.name = name;
6
+ this.data = data || [];
7
+ this.view = {
8
+ options: {},
9
+ data: [] //Array.from(this.data).slice()
10
+ };
11
+ this.options = options || {};
12
+ this.plugins = {
13
+ start: [],
14
+ select: [],
15
+ order: [],
16
+ render: [],
17
+ finish: []
18
+ };
19
+ }
20
+
21
+ ViewModel.prototype.update = function(params) {
22
+ if (!params) {
23
+ params = {};
24
+ }
25
+ if (params.data) {
26
+ // this.data is a reference to the data passed, so that any changes in it will get applied
27
+ // to the original
28
+ this.data = params.data;
29
+ }
30
+ // the view is a shallow copy of the array, so that changes in sort order and filtering
31
+ // won't get applied to the original, but databindings on its children will still work
32
+ this.view.data = Array.from(this.data).slice();
33
+ var plugins = this.plugins.start.concat(this.plugins.select, this.plugins.order, this.plugins.render, this.plugins.finish);
34
+ var self = this;
35
+ plugins.forEach(function(plugin) {
36
+ plugin.call(self, params);
37
+ });
38
+
39
+ if (global.editor) {
40
+ global.editor.addDataSource(this.name,{
41
+ load: function(el, callback) {
42
+ callback(self.view.data);
43
+ }
44
+ });
45
+ updateDataSource(this.name);
46
+ }
47
+ };
48
+
49
+ ViewModel.prototype.addPlugin = function(pipe, plugin) {
50
+ if (typeof this.plugins[pipe] == 'undefined') {
51
+ throw new Error('Unknown pipeline '+pipe);
52
+ }
53
+ this.plugins[pipe].push(plugin);
54
+ };
55
+
56
+ ViewModel.prototype.removePlugin = function(pipe, plugin) {
57
+ if (typeof this.plugins[pipe] == 'undefined') {
58
+ throw new Error('Unknown pipeline '+pipe);
59
+ }
60
+ this.plugins[pipe] = this.plugins[pipe].filter(function(p) {
61
+ return p != plugin;
62
+ });
63
+ };
64
+
65
+ var updateDataSource = function(name) {
66
+ global.document.querySelectorAll('[data-simply-data="'+name+'"]').forEach(function(list) {
67
+ global.editor.list.applyDataSource(list, name);
68
+ });
69
+ };
70
+
71
+ var createSort = function(options) {
72
+ var defaultOptions = {
73
+ name: 'sort',
74
+ getSort: function(params) {
75
+ return Array.prototype.sort;
76
+ }
77
+ };
78
+ options = Object.assign(defaultOptions, options || {});
79
+
80
+ return function(params) {
81
+ this.options[options.name] = options;
82
+ if (params[options.name]) {
83
+ options = Object.assign(options, params[options.name]);
84
+ }
85
+ this.view.data.sort(options.getSort.call(this, options));
86
+ };
87
+ };
88
+
89
+ var createPaging = function(options) {
90
+ var defaultOptions = {
91
+ name: 'paging',
92
+ page: 1,
93
+ pageSize: 100,
94
+ max: 1,
95
+ prev: 0,
96
+ next: 0
97
+ };
98
+ options = Object.assign(defaultOptions, options || {});
99
+
100
+ return function(params) {
101
+ this.options[options.name] = options;
102
+ if (this.view.data) {
103
+ options.max = Math.max(1, Math.ceil(Array.from(this.view.data).length / options.pageSize));
104
+ } else {
105
+ options.max = 1;
106
+ }
107
+ if (this.view.changed) {
108
+ options.page = 1; // reset to page 1 when something in the view data has changed
109
+ }
110
+ if (params[options.name]) {
111
+ options = Object.assign(options, params[options.name]);
112
+ }
113
+ options.page = Math.max(1, Math.min(options.max, options.page)); // clamp page nr
114
+ options.prev = options.page - 1; // calculate previous page, 0 is allowed
115
+ if (options.page<options.max) {
116
+ options.next = options.page + 1;
117
+ } else {
118
+ options.next = 0; // no next page
119
+ }
120
+
121
+ var start = (options.page - 1) * options.pageSize;
122
+ var end = start + options.pageSize;
123
+
124
+ this.view.data = this.view.data.slice(start, end);
125
+ };
126
+ };
127
+
128
+ var createFilter = function(options) {
129
+ var defaultOptions = {
130
+ name: 'filter',
131
+ label: 'A filter',
132
+ getMatch: function(entry) {
133
+ return false;
134
+ }
135
+ };
136
+ options = Object.assign(defaultOptions, options || {});
137
+ if (options.init) {
138
+ options.init.call(this, options);
139
+ }
140
+ return function(params) {
141
+ this.options[options.name] = options;
142
+ if (params[options.name]) {
143
+ options = Object.assign(options, params[options.name]);
144
+ }
145
+ var match = options.getMatch.call(this, options);
146
+ if (match) {
147
+ options.enabled = true;
148
+ this.view.data = this.view.data.filter(match);
149
+ } else if (options.enabled) {
150
+ options.enabled = false;
151
+ }
152
+ }
153
+ }
154
+
155
+ var viewmodel = {
156
+ create: function(name, data, options) {
157
+ return new ViewModel(name, data, options);
158
+ },
159
+ createFilter: createFilter,
160
+ createSort: createSort,
161
+ createPaging: createPaging,
162
+ updateDataSource: updateDataSource
163
+ };
164
+
165
+ if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') {
166
+ module.exports = viewmodel;
167
+ } else {
168
+ if (!global.simply) {
169
+ global.simply = {};
170
+ }
171
+ global.simply.viewmodel = viewmodel;
172
+ }
173
+
174
+ })(this);
package/make CHANGED
@@ -1,4 +1,18 @@
1
1
  #!/bin/bash
2
2
  rm dist/simply.everything.js
3
- find ./js/ -type f \( -iname "*.js" ! -iname "simply.include.next.js" \) -exec cat {} \; >> dist/simply.everything.js
4
- cp ./js/simply.include.next.js dist/
3
+ cat js/simply.observe.js \
4
+ js/simply.render.js \
5
+ js/simply.path.js \
6
+ js/simply.route.js \
7
+ js/simply.activate.js \
8
+ js/simply.collect.js \
9
+ js/simply.command.js \
10
+ js/simply.keyboard.js \
11
+ js/simply.action.js \
12
+ js/simply.resize.js \
13
+ js/simply.include.js \
14
+ js/simply.view.js \
15
+ js/simply.viewmodel.js \
16
+ js/simply.api.js \
17
+ js/simply.app.js > dist/simply.everything.js
18
+ cp js/simply.include.next.js dist/
package/make~ ADDED
@@ -0,0 +1,17 @@
1
+ #!/bin/bash
2
+ rm dist/simply.everything.js
3
+ cat js/simply.observe.js \
4
+ js/simply.render.js \
5
+ js/simply.path.js \
6
+ js/simply.route.js \
7
+ js/simply.activate.js \
8
+ js/simply.collect.js \
9
+ js/simply.command.js \
10
+ js/simply.action.js \
11
+ js/simply.resize.js \
12
+ js/simply.include.js \
13
+ js/simply.view.js \
14
+ js/simply.viewmodel.js \
15
+ js/simply.api.js \
16
+ js/simply.app.js > dist/simply.everything.js
17
+ cp js/simply.include.next.js dist/
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "simplyview",
3
- "version": "1.0.0",
3
+ "version": "2.0.2",
4
4
  "description": "Library to rapidly build UI components, using declarative tools",
5
5
  "main": "dist/simply.everything.js",
6
6
  "directories": {
7
7
  "example": "examples"
8
8
  },
9
9
  "scripts": {
10
- "test": "echo \"Error: no test specified\" && exit 1"
10
+ "test": "jest"
11
11
  },
12
12
  "repository": {
13
13
  "type": "git",
@@ -24,5 +24,8 @@
24
24
  "bugs": {
25
25
  "url": "https://github.com/simplyedit/simplyview/issues"
26
26
  },
27
- "homepage": "https://github.com/simplyedit/simplyview#readme"
27
+ "homepage": "https://github.com/simplyedit/simplyview#readme",
28
+ "devDependencies": {
29
+ "jest": "^24.9.0"
30
+ }
28
31
  }
package/package.json~ CHANGED
@@ -1,17 +1,17 @@
1
1
  {
2
2
  "name": "simplyview",
3
- "version": "1.0.0",
3
+ "version": "2.0.1",
4
4
  "description": "Library to rapidly build UI components, using declarative tools",
5
5
  "main": "dist/simply.everything.js",
6
6
  "directories": {
7
7
  "example": "examples"
8
8
  },
9
9
  "scripts": {
10
- "test": "echo \"Error: no test specified\" && exit 1"
10
+ "test": "jest"
11
11
  },
12
12
  "repository": {
13
13
  "type": "git",
14
- "url": "git+https://github.com/simplyedit/simplyview%2Cgit.git"
14
+ "url": "git+https://github.com/simplyedit/simplyview.git"
15
15
  },
16
16
  "keywords": [
17
17
  "UI",
@@ -22,7 +22,10 @@
22
22
  "author": "auke@muze.nl",
23
23
  "license": "MIT",
24
24
  "bugs": {
25
- "url": "https://github.com/simplyedit/simplyview%2Cgit/issues"
25
+ "url": "https://github.com/simplyedit/simplyview/issues"
26
26
  },
27
- "homepage": "https://github.com/simplyedit/simplyview%2Cgit#readme"
27
+ "homepage": "https://github.com/simplyedit/simplyview#readme",
28
+ "devDependencies": {
29
+ "jest": "^24.9.0"
30
+ }
28
31
  }
@@ -0,0 +1,102 @@
1
+ simplyRoute = require('../js/simply.route.js');
2
+
3
+ test('match fixed url', () => {
4
+ simplyRoute.load({
5
+ '/foo/': function(params) {
6
+ return 'bar';
7
+ }
8
+ });
9
+ expect(simplyRoute.match('/foo/')).toBe('bar');
10
+ });
11
+
12
+ test('match only from start', () => {
13
+ simplyRoute.load({
14
+ '/foo/': function(params) {
15
+ return 'bar';
16
+ },
17
+ '/oo/': function(params) {
18
+ return 'foobar';
19
+ }
20
+ });
21
+ expect(simplyRoute.match('oo/')).toBe('foobar');
22
+ });
23
+
24
+ test('match parameter', () => {
25
+ simplyRoute.load({
26
+ '/bar/:id' : function(params) {
27
+ return params.id;
28
+ }
29
+ });
30
+ expect(simplyRoute.match('bar/foobar')).toBe('foobar');
31
+ });
32
+
33
+ test('multiple parameters', () => {
34
+ simplyRoute.load({
35
+ '/baz/:id/:page' : function(params) {
36
+ return params.id+':'+params.page;
37
+ }
38
+ });
39
+ expect(simplyRoute.match('baz/foobar/1')).toBe('foobar:1');
40
+ });
41
+
42
+ test('match listener', () => {
43
+ simplyRoute.addListener('match', 'oo/', function(args) {
44
+ args.path = 'foo/';
45
+ return args;
46
+ });
47
+ simplyRoute.load({
48
+ '/oo/': function(params) {
49
+ return 'foobar';
50
+ },
51
+ '/foo/': function(params) {
52
+ return 'bar';
53
+ }
54
+ });
55
+ expect(simplyRoute.match('oo/')).toBe('bar');
56
+ });
57
+
58
+ test('call listener', () => {
59
+ simplyRoute.clear();
60
+ simplyRoute.addListener('call', 'foo/:id', function(args) {
61
+ args.params.id = 'foo'+args.params.id;
62
+ return args;
63
+ });
64
+ simplyRoute.load({
65
+ '/foo/:id': function(params) {
66
+ return params.id;
67
+ }
68
+ });
69
+ expect(simplyRoute.match('foo/bar')).toBe('foobar');
70
+ });
71
+
72
+ test('remove listener', () => {
73
+ simplyRoute.clear();
74
+ var callback = function(args) {
75
+ args.params.id = 'foo'+args.params.id;
76
+ return args;
77
+ };
78
+ simplyRoute.addListener('call', 'foo/:id', callback);
79
+ simplyRoute.load({
80
+ '/foo/:id': function(params) {
81
+ return params.id;
82
+ }
83
+ });
84
+ simplyRoute.removeListener('call','foo/:id', callback);
85
+ expect(simplyRoute.match('foo/bar')).toBe('bar');
86
+ });
87
+
88
+ test('multiple listeners', () => {
89
+ simplyRoute.clear();
90
+ simplyRoute.addListener('call', 'foo/:id', function(args) {
91
+ args.params.id+='1';
92
+ });
93
+ simplyRoute.addListener('call', 'foo/:id', function(args) {
94
+ args.params.id+='2';
95
+ });
96
+ simplyRoute.load({
97
+ '/foo/:id': function(params) {
98
+ return params.id;
99
+ }
100
+ });
101
+ expect(simplyRoute.match('foo/bar')).toBe('bar12');
102
+ });
@@ -1,50 +0,0 @@
1
- <h1>Examples</h1>
2
- <h2>Counter</h2>
3
- <link rel="stylesheet" href="examples.css">
4
-
5
- <div id="todoApp">
6
- <form data-simply-command="addEntry">
7
- <input type="text" name="newItem" class="new-todo" placeholder="What needs to be done?" autocomplete="off">
8
- </form>
9
- <ul class="todo-list" data-simply-list="items">
10
- <template>
11
- <li>
12
- <label data-simply-field="item">Item</label>
13
- </li>
14
- </template>
15
- </ul>
16
- </div>
17
- <script src="../dist/simply.everything.js"></script>
18
- <script>
19
- var todoApp = simply.app({
20
- bind: {
21
- twoway: false
22
- },
23
- container: document.getElementById('todoApp'),
24
- commands: {
25
- addEntry: function(form, values) {
26
- todoApp.actions.addEntry(values.newItem);
27
- form.elements.newItem.value = '';
28
- }
29
- },
30
- actions: {
31
- addEntry: function(item) {
32
- todoApp.view.items.push({
33
- item: item,
34
- completed: 0
35
- });
36
- return Promise.resolve();
37
- }
38
- },
39
- view: {
40
- items: [
41
- {
42
- item: 'iets'
43
- },
44
- {
45
- item: 'iets anders'
46
- }
47
- ]
48
- }
49
- });
50
- </script>