simplyview 2.0.1 → 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.
- package/dist/simply.everything.js +47 -1
- package/docs/simply.keyboard.md +60 -0
- package/examples/counter.html +1 -0
- package/examples/keyboard.html +41 -0
- package/js/simply.app.js +2 -1
- package/js/simply.keyboard.js +45 -0
- package/make +1 -0
- package/make~ +17 -0
- package/package.json +1 -1
- package/package.json~ +1 -1
- package/js/simply.api.js~ +0 -225
|
@@ -1098,6 +1098,51 @@ properties for a given parent, keep seperate index for this?
|
|
|
1098
1098
|
}
|
|
1099
1099
|
|
|
1100
1100
|
})(this);
|
|
1101
|
+
(function(global) {
|
|
1102
|
+
'use strict';
|
|
1103
|
+
|
|
1104
|
+
function keyboard(app, config) {
|
|
1105
|
+
var keys = config;
|
|
1106
|
+
|
|
1107
|
+
if (!app) {
|
|
1108
|
+
app = {};
|
|
1109
|
+
}
|
|
1110
|
+
if (!app.container) {
|
|
1111
|
+
app.container = document.body;
|
|
1112
|
+
}
|
|
1113
|
+
app.container.addEventListener('keydown', (e) => {
|
|
1114
|
+
if (e.isComposing || e.keyCode === 229) {
|
|
1115
|
+
return;
|
|
1116
|
+
}
|
|
1117
|
+
if (e.defaultPrevented) {
|
|
1118
|
+
return;
|
|
1119
|
+
}
|
|
1120
|
+
if (!e.target) {
|
|
1121
|
+
return;
|
|
1122
|
+
}
|
|
1123
|
+
|
|
1124
|
+
let selectedKeyboard = 'default';
|
|
1125
|
+
if (e.target.closest('[data-simply-keyboard]')) {
|
|
1126
|
+
selectedKeyboard = e.target.closest('[data-simply-keyboard]').dataset.simplyKeyboard;
|
|
1127
|
+
}
|
|
1128
|
+
if (keys[selectedKeyboard] && keys[selectedKeyboard][e.code]) {
|
|
1129
|
+
keys[selectedKeyboard][e.code].call(app,e);
|
|
1130
|
+
}
|
|
1131
|
+
});
|
|
1132
|
+
|
|
1133
|
+
return keys;
|
|
1134
|
+
}
|
|
1135
|
+
|
|
1136
|
+
|
|
1137
|
+
if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') {
|
|
1138
|
+
module.exports = keyboard;
|
|
1139
|
+
} else {
|
|
1140
|
+
if (!global.simply) {
|
|
1141
|
+
global.simply = {};
|
|
1142
|
+
}
|
|
1143
|
+
global.simply.keyboard = keyboard;
|
|
1144
|
+
}
|
|
1145
|
+
})(this);
|
|
1101
1146
|
(function(global) {
|
|
1102
1147
|
'use strict';
|
|
1103
1148
|
|
|
@@ -1986,7 +2031,8 @@ properties for a given parent, keep seperate index for this?
|
|
|
1986
2031
|
simply.route.match(global.location.pathname+global.location.hash);
|
|
1987
2032
|
});
|
|
1988
2033
|
}
|
|
1989
|
-
this.container = options.container
|
|
2034
|
+
this.container = options.container || document.body;
|
|
2035
|
+
this.keyboard = simply.keyboard ? simply.keyboard(this, options.keyboard || {}) : false;
|
|
1990
2036
|
this.actions = simply.action ? simply.action(this, options.actions) : false;
|
|
1991
2037
|
this.commands = simply.command ? simply.command(this, options.commands) : false;
|
|
1992
2038
|
this.resize = simply.resize ? simply.resize(this, options.resize) : false;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# simply.keyboard
|
|
2
|
+
|
|
3
|
+
simply.keyboard is a simple library to add keyboard support to your application:
|
|
4
|
+
|
|
5
|
+
```javascript
|
|
6
|
+
let myKeys = {
|
|
7
|
+
default: {
|
|
8
|
+
ArrowDown: (e) => {
|
|
9
|
+
// handle arrow down
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
simply.keyboard(myApp, myKeys);
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
But generally you won't use this directly, but through simply.app:
|
|
17
|
+
|
|
18
|
+
```javascript
|
|
19
|
+
var myApp = simply.app({
|
|
20
|
+
keyboard: {
|
|
21
|
+
default: {
|
|
22
|
+
ArrowDown: (e) => {
|
|
23
|
+
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
You can add multiple keyboard definitions:
|
|
31
|
+
|
|
32
|
+
```javascript
|
|
33
|
+
var counterApp = simply.app({
|
|
34
|
+
keyboard: {
|
|
35
|
+
default: {
|
|
36
|
+
ArrowDown: (e) => {
|
|
37
|
+
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
alternate: {
|
|
41
|
+
ArrowDown: (e) => {
|
|
42
|
+
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
The default keyboard is 'default', but you can switch the keyboard by setting this attribute:
|
|
50
|
+
|
|
51
|
+
```html
|
|
52
|
+
<div data-simply-keyboard="alternate">
|
|
53
|
+
<input type="text" name="example">
|
|
54
|
+
</div>
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Whenever a keyboard `keydown` is fired, simply.keyboard will look for the closest parent with a `data-simply-keyboard` attribute. If found, it will use that keyboard definition. If not found, it will use `default`.
|
|
58
|
+
|
|
59
|
+
The `keydown` event is only handled if the activeElement (the element that has focus) is inside the application container. See `simply.app` for more on that.
|
|
60
|
+
|
package/examples/counter.html
CHANGED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
<h1>Examples</h1>
|
|
2
|
+
<h2>Keyboard</h2>
|
|
3
|
+
<link rel="stylesheet" href="examples.css">
|
|
4
|
+
|
|
5
|
+
<div id="myApp">
|
|
6
|
+
<input type="text" data-simply-field="counter">
|
|
7
|
+
<button data-simply-command="add1">+</button>
|
|
8
|
+
<button data-simply-command="sub1">-</button>
|
|
9
|
+
<div>Counter is now: <span data-simply-field="counter"></span></div>
|
|
10
|
+
</div>
|
|
11
|
+
|
|
12
|
+
<script src="../dist/simply.everything.js"></script>
|
|
13
|
+
<script src="//cdn.simplyedit.io/1/simply-edit.js"></script>
|
|
14
|
+
<script>
|
|
15
|
+
var myApp = simply.app({
|
|
16
|
+
container: document.getElementById('myApp'),
|
|
17
|
+
keyboard: {
|
|
18
|
+
default: {
|
|
19
|
+
ArrowDown: function(e) {
|
|
20
|
+
this.view.counter--;
|
|
21
|
+
e.preventDefault();
|
|
22
|
+
},
|
|
23
|
+
ArrowUp: function(e) {
|
|
24
|
+
this.view.counter++;
|
|
25
|
+
e.preventDefault();
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
commands: {
|
|
30
|
+
add1: function(el, value) {
|
|
31
|
+
this.app.view.counter++;
|
|
32
|
+
},
|
|
33
|
+
sub1: function(el, value) {
|
|
34
|
+
this.app.view.counter--;
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
view: {
|
|
38
|
+
counter: 1
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
</script>
|
package/js/simply.app.js
CHANGED
|
@@ -29,7 +29,8 @@
|
|
|
29
29
|
simply.route.match(global.location.pathname+global.location.hash);
|
|
30
30
|
});
|
|
31
31
|
}
|
|
32
|
-
this.container = options.container
|
|
32
|
+
this.container = options.container || document.body;
|
|
33
|
+
this.keyboard = simply.keyboard ? simply.keyboard(this, options.keyboard || {}) : false;
|
|
33
34
|
this.actions = simply.action ? simply.action(this, options.actions) : false;
|
|
34
35
|
this.commands = simply.command ? simply.command(this, options.commands) : false;
|
|
35
36
|
this.resize = simply.resize ? simply.resize(this, options.resize) : false;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
(function(global) {
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
function keyboard(app, config) {
|
|
5
|
+
var keys = config;
|
|
6
|
+
|
|
7
|
+
if (!app) {
|
|
8
|
+
app = {};
|
|
9
|
+
}
|
|
10
|
+
if (!app.container) {
|
|
11
|
+
app.container = document.body;
|
|
12
|
+
}
|
|
13
|
+
app.container.addEventListener('keydown', (e) => {
|
|
14
|
+
if (e.isComposing || e.keyCode === 229) {
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
if (e.defaultPrevented) {
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
if (!e.target) {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
let selectedKeyboard = 'default';
|
|
25
|
+
if (e.target.closest('[data-simply-keyboard]')) {
|
|
26
|
+
selectedKeyboard = e.target.closest('[data-simply-keyboard]').dataset.simplyKeyboard;
|
|
27
|
+
}
|
|
28
|
+
if (keys[selectedKeyboard] && keys[selectedKeyboard][e.code]) {
|
|
29
|
+
keys[selectedKeyboard][e.code].call(app,e);
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
return keys;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') {
|
|
38
|
+
module.exports = keyboard;
|
|
39
|
+
} else {
|
|
40
|
+
if (!global.simply) {
|
|
41
|
+
global.simply = {};
|
|
42
|
+
}
|
|
43
|
+
global.simply.keyboard = keyboard;
|
|
44
|
+
}
|
|
45
|
+
})(this);
|
package/make
CHANGED
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
package/package.json~
CHANGED
package/js/simply.api.js~
DELETED
|
@@ -1,225 +0,0 @@
|
|
|
1
|
-
(function(global) {
|
|
2
|
-
'use strict';
|
|
3
|
-
|
|
4
|
-
var api = {
|
|
5
|
-
/**
|
|
6
|
-
* Returns a Proxy object that translates property access to a URL in the api
|
|
7
|
-
* and method calls to a fetch on that URL.
|
|
8
|
-
* @param options: a list of options for fetch(),
|
|
9
|
-
* see the 'init' parameter at https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch#parameters
|
|
10
|
-
* additionally:
|
|
11
|
-
* - baseURL: (required) the endpoint of the API
|
|
12
|
-
* - path: the current path in the API, is appended to the baseURL
|
|
13
|
-
* - verbs: list of http verbs to allow as methods, default ['get','post']
|
|
14
|
-
* - handlers.fetch: alternative fetch method
|
|
15
|
-
* - handlers.result: alternative getResult method
|
|
16
|
-
* - handlers.error: alternative error method
|
|
17
|
-
* - user (and password): if set, a basic authentication header will be added
|
|
18
|
-
* - paramsFormat: either 'formData', 'json' or 'search'. Default is search.
|
|
19
|
-
* - responseFormat: test, formData, blob, json, arrayBuffer or unbuffered. Default is json.
|
|
20
|
-
* @return Proxy
|
|
21
|
-
*/
|
|
22
|
-
proxy: function(options) {
|
|
23
|
-
var cache = () => {};
|
|
24
|
-
cache.$options = Object.assign({}, options);
|
|
25
|
-
return new Proxy( cache, getApiHandler(cache.$options) );
|
|
26
|
-
},
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Fetches the options.baseURL using the fetch api and returns a promise
|
|
30
|
-
* Extra options in addition to those of global.fetch():
|
|
31
|
-
* - user (and password): if set, a basic authentication header will be added
|
|
32
|
-
* - paramsFormat: either 'formData', 'json' or 'search'
|
|
33
|
-
* By default params, if set, will be added to the baseURL as searchParams
|
|
34
|
-
* @param method one of the http verbs, e.g. get, post, etc.
|
|
35
|
-
* @param options the options for fetch(), with some additions
|
|
36
|
-
* @param params the parameters to send with the request, as javascript/json data
|
|
37
|
-
* @return Promise
|
|
38
|
-
*/
|
|
39
|
-
fetch: function(method, params, options) {
|
|
40
|
-
if (!options.url) {
|
|
41
|
-
if (!options.baseURL) {
|
|
42
|
-
throw new Error('No url or baseURL in options object');
|
|
43
|
-
}
|
|
44
|
-
while (options.baseURL[options.baseURL.length-1]=='/') {
|
|
45
|
-
options.baseURL = options.baseURL.substr(0, options.baseURL.length-1);
|
|
46
|
-
}
|
|
47
|
-
var url = new URL(options.baseURL+options.path);
|
|
48
|
-
} else {
|
|
49
|
-
var url = options.url;
|
|
50
|
-
}
|
|
51
|
-
var fetchOptions = Object.assign({}, options);
|
|
52
|
-
if (!fetchOptions.headers) {
|
|
53
|
-
fetchOptions.headers = {};
|
|
54
|
-
}
|
|
55
|
-
if (params) {
|
|
56
|
-
if (method=='GET') {
|
|
57
|
-
var paramsFormat = 'search';
|
|
58
|
-
} else {
|
|
59
|
-
var paramsFormat = options.paramsFormat;
|
|
60
|
-
}
|
|
61
|
-
switch(paramsFormat) {
|
|
62
|
-
case 'formData':
|
|
63
|
-
var formData = new FormData();
|
|
64
|
-
for (const name in params) {
|
|
65
|
-
formData.append(name, params[name]);
|
|
66
|
-
}
|
|
67
|
-
if (!fetchOptions.headers['Content-Type']) {
|
|
68
|
-
fetchOptions.headers['Content-Type'] = 'application/x-www-form-urlencoded';
|
|
69
|
-
}
|
|
70
|
-
break;
|
|
71
|
-
case 'json':
|
|
72
|
-
var formData = JSON.stringify(params);
|
|
73
|
-
if (!fetchOptions.headers['Content-Type']) {
|
|
74
|
-
fetchOptions.headers['Content-Type'] = 'application/json';
|
|
75
|
-
}
|
|
76
|
-
break;
|
|
77
|
-
case 'search':
|
|
78
|
-
var searchParams = url.searchParams; //new URLSearchParams(url.search.slice(1));
|
|
79
|
-
for (const name in params) {
|
|
80
|
-
searchParams.set(name, params[name]);
|
|
81
|
-
}
|
|
82
|
-
url.search = searchParams.toString();
|
|
83
|
-
break;
|
|
84
|
-
default:
|
|
85
|
-
throw Error('Unknown options.paramsFormat '+options.paramsFormat+'. Select one of formData, json or search.');
|
|
86
|
-
break;
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
if (formData) {
|
|
90
|
-
fetchOptions.body = formData
|
|
91
|
-
}
|
|
92
|
-
if (options.user) {
|
|
93
|
-
fetchOptions.headers['Authorization'] = 'Basic '+btoa(options.user+':'+options.password);
|
|
94
|
-
}
|
|
95
|
-
fetchOptions.method = method.toUpperCase();
|
|
96
|
-
var fetchURL = url.toString()
|
|
97
|
-
return fetch(fetchURL, fetchOptions);
|
|
98
|
-
},
|
|
99
|
-
graphqlQuery: function(url, operationName, query, options) {
|
|
100
|
-
options = Object.assign({ paramsFormat: 'json', url: url, responseFormat: 'json' }, options)
|
|
101
|
-
return function(params) {
|
|
102
|
-
return simply.api.fetch(
|
|
103
|
-
'POST',
|
|
104
|
-
{
|
|
105
|
-
operationName: operationName,
|
|
106
|
-
query: query,
|
|
107
|
-
variables: params || {}
|
|
108
|
-
},
|
|
109
|
-
options
|
|
110
|
-
).then(function(response) {
|
|
111
|
-
return simply.api.getResult(response, options);
|
|
112
|
-
});
|
|
113
|
-
}
|
|
114
|
-
},
|
|
115
|
-
/**
|
|
116
|
-
* Handles the response and returns a Promise with the response data as specified
|
|
117
|
-
* @param response Response
|
|
118
|
-
* @param options
|
|
119
|
-
* - responseFormat: one of 'text', 'formData', 'blob', 'arrayBuffer', 'unbuffered' or 'json'.
|
|
120
|
-
* The default is json.
|
|
121
|
-
*/
|
|
122
|
-
getResult: function(response, options) {
|
|
123
|
-
if (response.ok) {
|
|
124
|
-
switch(options.responseFormat) {
|
|
125
|
-
case 'text':
|
|
126
|
-
return response.text();
|
|
127
|
-
break;
|
|
128
|
-
case 'formData':
|
|
129
|
-
return response.formData();
|
|
130
|
-
break;
|
|
131
|
-
case 'blob':
|
|
132
|
-
return response.blob();
|
|
133
|
-
break;
|
|
134
|
-
case 'arrayBuffer':
|
|
135
|
-
return response.arrayBuffer();
|
|
136
|
-
break;
|
|
137
|
-
case 'unbuffered':
|
|
138
|
-
return response.body;
|
|
139
|
-
break;
|
|
140
|
-
case 'json':
|
|
141
|
-
default:
|
|
142
|
-
return response.json();
|
|
143
|
-
break;
|
|
144
|
-
}
|
|
145
|
-
} else {
|
|
146
|
-
throw {
|
|
147
|
-
status: response.status,
|
|
148
|
-
message: response.statusText,
|
|
149
|
-
response: response
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
},
|
|
153
|
-
logError: function(error, options) {
|
|
154
|
-
console.error(error.status, error.message);
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
var defaultOptions = {
|
|
159
|
-
path: '',
|
|
160
|
-
responseFormat: 'json',
|
|
161
|
-
paramsFormat: 'search',
|
|
162
|
-
verbs: ['get','post'],
|
|
163
|
-
handlers: {
|
|
164
|
-
fetch: api.fetch,
|
|
165
|
-
result: api.getResult,
|
|
166
|
-
error: api.logError
|
|
167
|
-
}
|
|
168
|
-
};
|
|
169
|
-
|
|
170
|
-
function cd(path, name) {
|
|
171
|
-
name = name.replace(/\//g,'');
|
|
172
|
-
if (!path.length || path[path.length-1]!=='/') {
|
|
173
|
-
path+='/';
|
|
174
|
-
}
|
|
175
|
-
return path+encodeURIComponent(name);
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
function fetchChain(prop, params) {
|
|
179
|
-
var options = this;
|
|
180
|
-
return this.handlers.fetch
|
|
181
|
-
.call(this, prop, params, options)
|
|
182
|
-
.then(function(res) {
|
|
183
|
-
return options.handlers.result.call(options, res, options);
|
|
184
|
-
})
|
|
185
|
-
.catch(function(error) {
|
|
186
|
-
return options.handlers.error.call(options, error, options);
|
|
187
|
-
});
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
function getApiHandler(options) {
|
|
191
|
-
options.handlers = Object.assign({}, defaultOptions.handlers, options.handlers);
|
|
192
|
-
options = Object.assign({}, defaultOptions, options);
|
|
193
|
-
|
|
194
|
-
return {
|
|
195
|
-
get: function(cache, prop) {
|
|
196
|
-
if (!cache[prop]) {
|
|
197
|
-
if (options.verbs.indexOf(prop)!=-1) {
|
|
198
|
-
cache[prop] = function(params) {
|
|
199
|
-
return fetchChain.call(options, prop, params);
|
|
200
|
-
}
|
|
201
|
-
} else {
|
|
202
|
-
cache[prop] = api.proxy(Object.assign({}, options, {
|
|
203
|
-
path: cd(options.path, prop)
|
|
204
|
-
}));
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
return cache[prop];
|
|
208
|
-
},
|
|
209
|
-
apply: function(cache, thisArg, params) {
|
|
210
|
-
return fetchChain.call(options, 'get', params[0] ? params[0] : null)
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') {
|
|
217
|
-
module.exports = api;
|
|
218
|
-
} else {
|
|
219
|
-
if (!global.simply) {
|
|
220
|
-
global.simply = {};
|
|
221
|
-
}
|
|
222
|
-
global.simply.api = api;
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
})(this);
|