efront 4.3.3 → 4.3.5

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.
@@ -1,3 +1,9 @@
1
+ - zh-CN: 服务异常
2
+ en: Service exception
3
+
4
+ - zh-CN: 自动识别环境并启动测试环境服务器
5
+ en: Automatically recognize the environment and start the testing environment server
6
+
1
7
  - zh-CN: 返回
2
8
  en: back
3
9
 
@@ -56,7 +62,7 @@
56
62
  en: "The server is busy, please try again later!"
57
63
 
58
64
  - zh-CN: 重试
59
- en: retry
65
+ en: retry
60
66
 
61
67
  - zh-CN: $1秒后再试
62
68
  en: Try again in $1 second
@@ -1,7 +1,7 @@
1
1
  plist.bind(null, '任务管理', "task", refilm`
2
2
  *任务ID/key 100
3
3
  *任务名/name 100
4
- *是否启用/status radio [不启用,启用]
4
+ *是否启用/status radio 不启用,启用
5
5
  任务代码/code text
6
6
  / $ ${[
7
7
  {
@@ -1,6 +1,9 @@
1
1
  var mark = require("./mark");
2
+ var gray = console.format('<gray>;</gray>').split(';');
3
+ var green = console.format('<green>;</green>').split(';');
4
+ var crack = console.format('<red2>;</red2>').split(';');
2
5
  var dump = function (a, msg) {
3
- if (a instanceof Object) console.error('对象的属性不符合'), console.log(msg ? msg + " " : " ", a);
6
+ if (a instanceof Object) console.error('属性错误'), console.log(msg ? msg + " " : " {\r\n", Object.keys(a).map(k => ` ${k}${gray.join(':')}\r\n ${a[k]}`).join('\r\n') + "\r\n }");
4
7
  else if (msg) console.log(msg + ":", a);
5
8
  else console.log(a);
6
9
  };
@@ -38,9 +41,12 @@ var assert = function (result, expect, log = dump) {
38
41
  };
39
42
  return function (error) {
40
43
  if (error instanceof Object) {
41
- errors[k] = Object.keys(error).map(k => `${k} >> ${error[k]}`).join("\r\n");
44
+ Object.keys(error).forEach(y => {
45
+ var e = y;
46
+ errors[`${gray.join('[')}${green.join(k)}${gray.join("]->")}` + e] = error[y];
47
+ })
42
48
  } else {
43
- errors[k] = error;
49
+ errors[gray.join("[") + crack.join(k) + gray.join("]")] = error;
44
50
  }
45
51
  };
46
52
  };
@@ -78,7 +78,7 @@ var scan = function (text) {
78
78
  continue;
79
79
  }
80
80
  data += row.slice(0, index + +!!jsonlikes.length);
81
- row = row.slice(index + 1)
81
+ row = row.slice(index + 1);
82
82
  if (!row) push();
83
83
  else unshift(spacesize, row);
84
84
  rowtype = 0;
@@ -110,6 +110,7 @@ var scan = function (text) {
110
110
  continue;
111
111
  }
112
112
  if (/^["']/.test(row)) {
113
+ if (data) push();
113
114
  rowtype = row[0];
114
115
  if (jsonlikes.length) {
115
116
  data += row[0];
@@ -192,7 +193,8 @@ var scan = function (text) {
192
193
  continue;
193
194
  }
194
195
  else {
195
- var match = /^([\s\S]+)?\:(|\s+[\s\S]*)$/.exec(row);
196
+ var match = /^([\s\S]*?)\:(|\s+[\s\S]*)$/.exec(row);
197
+ if (data && !match) match = /^()\:([\s\S]*)$/.exec(row);
196
198
  if (match) {
197
199
  if (data && !!match[1] || prop && span >= spacesize) push();
198
200
  if (prop) {
@@ -3,46 +3,74 @@ var path = require("path");
3
3
  var fullpath = path.join(__dirname, "../../.github/workflows/npmpublish.yml");
4
4
  var text = fs.readFileSync(fullpath).toString();
5
5
  var parseYML = require("./parseYML");
6
- var text = [
7
- `true`,
8
- `- true`,
9
- ` true true`,
10
- ` a: true `,
11
- `false`,
12
- `null`,
13
- `a`,
14
- `"a"`,
15
- `'a'`,
16
- `[0,12]`,
17
- `[0,12,a,b]`,
18
- `[0,12,a,b,"c","d"]`,
19
- `{}`,
20
- `{a: b}`,
21
- `{"a":b}`,
22
- `{"a":[b,c,d]}`,
23
- `{"a":[b,{a},[c],[{}],c,d]}`,
24
- `{"a":{a: b},c: {},d: [c],e: [{j}]}`,
25
- `{"a":"[b,c,d]"}`,
26
- `{"a":false}`,
27
- `{"a":13e1}`,
28
- `{"a":1.21}`,
29
- `{"a":0x1a}`,
30
- `{"a":null}`,
31
- `{"a":true}`,
32
- `{"a":-12e71}`,
33
- `{"a":-12e+71}`,
34
- `{"a":-12}`,
35
- `{"a":-12.0}`,
36
- `{"a":-12.e-61}`,
37
- `{"a":+12.e-61}`,
38
- `{"a":12.e-61}`,
39
- `{"a":"[b,c,\r\n\\"d]"}`,
40
- ` - zh-CN: "跳过了缺少参数的请求:$1 $2 $3\\r\\n缺少参数:$4"
41
- en: "Skipped request with missing parameters: $1 $2 $3"`,
42
- text
43
- ];
44
- var test = function (text) {
45
- var data = parseYML(text);
46
- console.log(data);
47
- };
48
- text.forEach(test);
6
+ var test = function (source, expect) {
7
+ var result = parseYML(source);
8
+ var same = assert(result, expect);
9
+ if (!same) console.log(result);
10
+ }
11
+ test('true', true);
12
+ test('- true', [true]);
13
+ test('true true', "true true");
14
+ test('a: true', { a: true });
15
+ test('false', false);
16
+ test('null', null);
17
+ test('a', "a");
18
+ test('"a"', "a");
19
+ test(`'a'`, "a");
20
+ test("[0,12]", [0, 12]);
21
+ test("[0,12,a,b]", [0, 12, 'a', 'b']);
22
+ test("[0,12,a,b,'c','d']", [0, 12, 'a', 'b', 'c', 'd']);
23
+ test(`[0,12,a,b,"c","d"]`, [0, 12, 'a', 'b', "c", "d"]);
24
+ test(`{}`, {});
25
+ test(`{a: b}`, { a: 'b' });
26
+ test(`{"a":b}`, { a: 'b' });
27
+ test(`{a:[b,c,d]}`, { a: ['b', 'c', 'd'] });
28
+ test(`{a:[b,{a},[c],[{}],c,d]}`, { a: ['b', { a: null }, ["c"], [{}], "c", 'd'] });
29
+ test(`{"a":{a: b},c:{},d:[c],e:[{j}]}`, { a: { a: 'b' }, c: {}, d: ["c"], e: [{ j: null }] });
30
+ test(`{"a":"[b,c,d]"}`, { a: "[b,c,d]" });
31
+ test(`{"a":false}`, { a: false });
32
+ test(`{"a":13e1}`, { a: 13e1 });
33
+ test(`{"a":13e+1}`, { a: 13e1 });
34
+ test(`{"a":13e-1}`, { a: 13e-1 });
35
+ test(`{"a":1.21}`, { a: 1.21 });
36
+ test(`{"a":-1.21}`, { a: -1.21 });
37
+ test(`{"a":0x1a}`, { a: 0x1a });
38
+ test(`{"a":null}`, { a: null });
39
+ test(`{"a":true}`, { a: true });
40
+ test(`{"a":-12e71}`, { a: -12e71 });
41
+ test(`{"a":12e+71}`, { a: 12e+71 });
42
+ test(`12e+71`, 12e+71);
43
+ test(`-12e+71`, -12e+71);
44
+ test(`-12e-71`, -12e-71);
45
+ test(`-12.0`, -12.0);
46
+ test(`-12.e-61`, -12.e-61);
47
+ test(`+12.e-61`, 12.e-61);
48
+ test(`12.e-61`, 12.e-61);
49
+ test(`{"a":"[b,c,\r\n\\"d]"}`, { a: "[b,c,\r\n\"d]" });
50
+ test(`
51
+ - zh-CN: "跳过了缺少参数的请求:$1 $2 $3\\r\\n缺少参数:$4"
52
+ en: "Skipped request with missing parameters: $1 $2 $3"`,
53
+ [{
54
+ "zh-CN": "跳过了缺少参数的请求:$1 $2 $3\r\n缺少参数:$4",
55
+ "en": "Skipped request with missing parameters: $1 $2 $3"
56
+ }]);
57
+ test(`
58
+ - zh-CN: 未没找到匹配的资源:$1
59
+ en: "No matching resources found: $1"
60
+ `, [{
61
+ "zh-CN": "未没找到匹配的资源:$1",
62
+ "en": "No matching resources found: $1"
63
+ }]);
64
+ test(`- a:: b`, [{ "a:": "b" }]);
65
+ test(`- a::b`, ["a::b"]);
66
+ test(`a::b`, "a::b");
67
+ test(`a:":b`, `a:":b`);
68
+ test(`a:": b`, { 'a:"': "b" });
69
+ test(`a: :b`, { "a": ":b" });
70
+ test(`a:: b`, { "a:": "b" });
71
+ test(`"a:": b`, { "a:": "b" });
72
+ test(`"a:":b`, { "a:": "b" });
73
+ test(`
74
+ c: d
75
+ "a:": b
76
+ `, { c: "d", "a:": "b" });
@@ -132,7 +132,9 @@ function unfoldOptions(size, options) {
132
132
  for (var cx = 0, dx = options.length; cx < dx; cx++) {
133
133
  var o = options[cx];
134
134
  if (typeof o === 'string') {
135
- o = { name: o, key: o };
135
+ var [name, key = name] = spreadkey(o);
136
+ if (parseInt(key) === +key) key = +key;
137
+ o = { name, key };
136
138
  }
137
139
  var range = rangereg.exec(o.name);
138
140
  if (range) {
@@ -236,6 +238,28 @@ var getComment = function (piece) {
236
238
  }
237
239
  return '';
238
240
  };
241
+ function spreadkey(name) {
242
+ if (/^\([\s\S]*\)$/.test(name) && /,/.test(name)) {
243
+ var [, name, rest_piece] = /^([\s\S]*?),([^\]]*)$/.exec(name.slice(1, name.length - 1));
244
+ if (rest_piece && !/=/.test(rest_piece)) {
245
+ var needs = { [name]: parseValue(rest_piece) };
246
+ } else {
247
+ var needs = scanNeeds(rest_piece);
248
+ }
249
+ }
250
+ if (/^\[[\s\S]*\]$/.test(name)) {
251
+ repeat = true;
252
+ name = name.replace(/^\[|\]$/g, '');
253
+ if (/\,/.test(name)) {
254
+ var commaindex = name.indexOf(",");
255
+ var endwith = parseKV(name.slice(commaindex + 1));
256
+ endwith = parseValue(endwith);
257
+ name = name.slice(0, commaindex);
258
+ }
259
+ }
260
+ var [name, key] = scanSlant(name, '/', 0, name.length + 1);
261
+ return [name, key, needs];
262
+ }
239
263
  function parse(piece) {
240
264
  if (/^[\-#]+$/.test(piece[0])) {
241
265
  var piece0 = piece.pop();
@@ -268,7 +292,8 @@ function parse(piece) {
268
292
  required, inlist, hidden, readonly,
269
293
  delete_onempty, delete_onsubmit,
270
294
  } = name;
271
- } else {
295
+ }
296
+ else if (typeof type === 'string') {
272
297
  var test = (reg, a) => {
273
298
  if (reg.test(a)) {
274
299
  return true;
@@ -305,25 +330,7 @@ function parse(piece) {
305
330
  last_type = type;
306
331
  }
307
332
  }
308
- if (/^\([\s\S]*\)$/.test(name) && /,/.test(name)) {
309
- var [, name, rest_piece] = /^([\s\S]*?),([^\]]*)$/.exec(name.slice(1, name.length - 1));
310
- if (rest_piece && !/=/.test(rest_piece)) {
311
- var needs = { [name]: parseValue(rest_piece) };
312
- } else {
313
- var needs = scanNeeds(rest_piece);
314
- }
315
- }
316
- if (/^\[[\s\S]*\]$/.test(name)) {
317
- repeat = true;
318
- name = name.replace(/^\[|\]$/g, '');
319
- if (/\,/.test(name)) {
320
- var commaindex = name.indexOf(",");
321
- var endwith = parseKV(name.slice(commaindex + 1));
322
- endwith = parseValue(endwith);
323
- name = name.slice(0, commaindex);
324
- }
325
- }
326
- [name, key] = scanSlant(name, '/', 0, name.length + 1);
333
+ [name, key, needs] = spreadkey(name);
327
334
  if (key === undefined && !/^(title|label|headline)$/i.test(type)) key = name;
328
335
  }
329
336
  if (/^[a-z\d]+\/?\d+$/i.test(type)) {
@@ -411,6 +418,9 @@ function parse(piece) {
411
418
  name = is(name);
412
419
  key = is(key);
413
420
  }
421
+ else if (typeof name === 'string') {
422
+ [name, key = name, needs] = spreadkey(name);
423
+ }
414
424
  if (typeof size === 'string') size = parseFloat(size);
415
425
  var field = {
416
426
  name, type, key, value, comment, options,
@@ -1,2 +1,19 @@
1
- var fields = refilm_decode(["启动时间/time $1"]);
2
- console.log(fields);
1
+ var refilm = function (a) {
2
+ return refilm_decode.apply(null, [a.raw].concat([].slice.call(arguments, 1)));
3
+ };
4
+ var test = function (fields, key, expect) {
5
+ var valid = assert(seek(fields[0], key), expect);
6
+ if (!valid) console.log(fields)
7
+ };
8
+ test(refilm`启动时间/time $1`, 'key', 'time');
9
+ test(refilm`启动时间/time $1`, 'type', '$1');
10
+ test(refilm`启动时间/time ${test}`, 'key', "time");
11
+ test(refilm`启动时间/time ${test}`, 'type', test);
12
+ test(refilm`天下第一 四人组 ${["天地玄黄", "湘西四鬼"]}`, 'key', "天下第一");
13
+ test(refilm`天下第一 四人组 ${["天地玄黄", "湘西四鬼"]}`, 'type', "四人组");
14
+ test(refilm`天下第一 四人组 ${["天地玄黄", "湘西四鬼"]}`, ['options', 1], "湘西四鬼");
15
+ test(refilm`连城剑法 别名 唐诗剑法,躺尸剑法`, ['options', 1], "躺尸剑法");
16
+ test(refilm`连城剑法 别名 [唐诗剑法,躺尸剑法]`, ['options', 1, 'name'], "躺尸剑法");
17
+ test(refilm`连城剑法 别名 [唐诗剑法,躺尸剑法]`, ['options', 1, 'key'], "躺尸剑法");
18
+ test(refilm`连城剑法 别名 [唐诗剑法,躺尸剑法]`, ['options', 1, 'value'], 1);
19
+ test(refilm`连城剑法 别名 [唐诗剑法/0,躺尸剑法/1]`, ['options', 1, 'key'], 1);
@@ -1535,6 +1535,7 @@ var down = function (scoped) {
1535
1535
  var inAsync = scoped.async;
1536
1536
  var inAster = scoped.yield;
1537
1537
  var funcMark = [, "aster_", "async_", "asyncAster_"][inAsync << 1 | inAster];
1538
+ if (funcMark) funcMark = patchMark + funcMark;
1538
1539
  if (funcMark) rootenvs[funcMark] = true;
1539
1540
  var vars = Object.assign(Object.create(null), scoped.vars);
1540
1541
  var envs = Object.assign(Object.create(null), scoped.envs);
@@ -1720,7 +1721,7 @@ var down = function (scoped) {
1720
1721
  if (funcMark) {
1721
1722
  var argname = _letname("_");
1722
1723
  unstruct.debug = downLevel.debug;
1723
- var body = scanner2(`return ${patchMark + funcMark}()`);
1724
+ var body = scanner2(`return ${funcMark}()`);
1724
1725
  var code = unawait(scoped.body, _getname, argname);
1725
1726
  code.forEach(function (c) {
1726
1727
  revar(c);
@@ -401,10 +401,11 @@ var getFromScopeList = function (name, varsList, value = name) {
401
401
  };
402
402
  var removeSelectorSpace = a => a.trim().replace(/\s*([\+~\>])\s*/g, "$1");
403
403
  var fixBase = function (b, a) {
404
- return a.split(/,\s*/).map(a => {
404
+ var s = splitParams(a);
405
+ return splitParams(a).map(a => {
405
406
  if (presets.test(a)) a = `@{${a}}`;
406
407
  var replaced = false;
407
- return b.split(/\s*,\s*/).map(b => {
408
+ return splitParams(b).map(b => {
408
409
  b = b.replace(/^(&|\:scope|\:root)\s*/g, "");
409
410
  if (!b) return a;
410
411
  var a1 = a.replace(/&|\:scope|\:root/g, function (match) {
@@ -71,4 +71,5 @@ assert(素馨(`.a (){ &:after{abc:1}} .b{.a();}`, '.abc-'), `.abc- .b:after{abc:
71
71
  assert(素馨(`@a:1px;@margin-x:@a+10px; a{m:-@margin-x}`), `a{m:-11px;}`);
72
72
  assert(素馨(`a{@a:1px;@margin-x:@a+10px;m:-@margin-x}`), `a{m:-11px;}`);
73
73
  assert(素馨(`@media screen{&.a{b:1}}`,'a'), `@media screen{a.a{b:1;}}`);
74
- assert(素馨(`@media screen and(max-width:100px){&.a{b:1}}`,'a'), `@media screen and (max-width:100px){a.a{b:1;}}`);
74
+ assert(素馨(`@media screen and(max-width:100px){&.a{b:1}}`,'a'), `@media screen and (max-width:100px){a.a{b:1;}}`);
75
+ assert(素馨(`b{:not([resizing], [dragging]) {transition: padding .2s, margin .2s;}}`), `b :not([resizing], [dragging]){transition:padding .2s, margin .2s;}`);
@@ -20,20 +20,30 @@ var touch = {
20
20
  * @type {Element}
21
21
  */
22
22
  var t = this;
23
- var a = this.$scope.toActive(e);
24
- touchitems = this.querySelectorAll("fileitem");
25
- if (a && this.$scope.selected.indexOf(a.$scope.d) >= 0) {
26
- dragger = e;
27
- if (!drag.target) drag(this.$scope.selected.length === 1 ? a : this.querySelectorAll(".focused"), e);
28
- return;
23
+ var start = () => {
24
+ if (onclick.preventClick) return;
25
+ var a = t.$scope.toActive(e);
26
+ touchitems = t.querySelectorAll("fileitem");
27
+ if (a && t.$scope.selected.indexOf(a.$scope.d) >= 0) {
28
+ dragger = e;
29
+ if (!drag.target) drag(t.$scope.selected.length === 1 ? a : t.querySelectorAll(".focused"), e);
30
+ return;
31
+ }
32
+ var pos = getScreenPosition(t.parentNode);
33
+ var pos2 = getScreenPosition(t.previousElementSibling);
34
+
35
+ rect.limit = [pos.left + t.parentNode.clientLeft, Math.max(pos.top, pos2.bottom + 1)];
36
+ rect.event = e;
37
+ rect.setAttribute('style', '');
38
+ css(rect, { left: e.clientX - pos.left - t.clientLeft, top: e.clientY - t.clientTop, width: 0, height: 0 })
39
+ };
40
+ if (/^touch/.test(e.type)) {
41
+ touch.ing = setTimeout(start, 600);
42
+ }
43
+ else {
44
+ start();
29
45
  }
30
- var pos = getScreenPosition(t.parentNode);
31
- var pos2 = getScreenPosition(t.previousElementSibling);
32
46
 
33
- rect.limit = [pos.left + t.parentNode.clientLeft, Math.max(pos.top, pos2.bottom + 1)];
34
- rect.event = e;
35
- rect.setAttribute('style', '');
36
- css(rect, { left: e.clientX - pos.left - t.clientLeft, top: e.clientY - t.clientTop, width: 0, height: 0 })
37
47
  },
38
48
  move(e) {
39
49
  if (!onclick.preventClick) return;
@@ -72,6 +82,7 @@ var touch = {
72
82
  }
73
83
  }
74
84
  if (!tiped && drag.tip) css(drag.tip, 'display:none');
85
+ e.moveLocked = 2;
75
86
  return;
76
87
  }
77
88
  if (e.type !== 'mousemove') return;
@@ -83,6 +94,7 @@ var touch = {
83
94
  },
84
95
  async end(e) {
85
96
  touchitems = null;
97
+ clearTimeout(touch.ing);
86
98
  if (dragger) {
87
99
  delete drag.tip;
88
100
  dragger = null;
@@ -40,7 +40,7 @@ var dragview = function (dragview) {
40
40
  page.style.transition = '';
41
41
  if (moving && moving !== -1) {
42
42
  var left = freeOffset(page.style.left || 0);
43
- if (moving.deltaX < 0 && left > offsetWidth * 0.3 || moving.deltaX > 0 && left > offsetWidth * 0.7 || !moving.deltaX && left > offsetWidth >> 1) {
43
+ if (moving.deltaX < 0 && left > calcPixel(14) || moving.deltaX > 0 && left > calcPixel(14) || !moving.deltaX && left > offsetWidth >> 1) {
44
44
  page.style.left = 0;
45
45
  dragview.toRight();
46
46
  } else {
@@ -1,5 +1,5 @@
1
- <div ng-class="{even:i%2===1,odd:i%2===0}" v-for="(r,i) in rates" hz:='r[5]'>
2
- <span ng-if="i%2===0" v-bind="i/2 -8"></span>
1
+ <div ng-class="{even:i&1,odd:!(i&1)}" v-for="(r,i) in rates" hz:='r[5]'>
2
+ <span ng-if="!(i&1)" v-bind="i/2 -8"></span>
3
3
  <button ng-repeat="o in r" _rate=o>
4
4
  <span ng-bind="format(o)"></span>
5
5
  </button>
@@ -11,45 +11,72 @@ function piano() {
11
11
  return res;
12
12
  }
13
13
  function main() {
14
- var page = vbox('x');
14
+ var page = document.createElement('div');
15
15
  page.innerHTML = AudioContext_test;
16
+ var mouse_target = null;
17
+ var setBuffer = function (btn) {
18
+ var { gainNode, audioCtx, oscillator } = btn;
19
+ var gain = gainNode.gain;
20
+ var hz = btn.rate;
21
+ var currentTime = audioCtx.currentTime;
22
+ gain.setValueAtTime(65536 / Math.log2(hz), currentTime + 0.01);
23
+ // gain.linearRampToValueAtTime(0, currentTime + 2);
24
+ gain.exponentialRampToValueAtTime(0.001, currentTime + 1);
25
+ };
26
+ var init = function (btn) {
27
+ if (btn.audioCtx) {
28
+ return btn;
29
+ }
30
+ var audioCtx = btn.audioCtx = new AudioContext();
31
+ var gainNode = btn.gainNode = audioCtx.createGain();
32
+ var oscillator = btn.oscillator = audioCtx.createOscillator();
33
+ var hz = btn.rate;
34
+ oscillator.connect(gainNode);
35
+ gainNode.connect(audioCtx.destination);
36
+ oscillator.type = 'sine';
37
+ oscillator.frequency.value = -hz;
38
+ oscillator.start(0);
39
+ return { audioCtx, gainNode, oscillator };
40
+ };
41
+ var drop = function (btn) {
42
+ btn.oscillator.stop();
43
+ btn.audioCtx = null;
44
+ btn.gainNode = null;
45
+ btn.oscillator = null;
46
+ }
16
47
  var click = {
17
- start() {
18
- if (this.audioCtx) return;
19
- var hz = this.rate;
20
- var audioCtx = this.audioCtx = new AudioContext();
21
- var gainNode = this.gainNode = audioCtx.createGain();
22
- var oscillator = this.oscillator = audioCtx.createOscillator();
23
- oscillator.connect(gainNode);
24
- gainNode.connect(audioCtx.destination);
25
- oscillator.type = 'sine';
26
- oscillator.frequency.value = -hz;
27
- gainNode.gain.setValueAtTime(0, audioCtx.currentTime);
28
- gainNode.gain.linearRampToValueAtTime(65536 / Math.log2(hz), audioCtx.currentTime + 0.01);
29
- oscillator.start(audioCtx.currentTime);
30
- addClass(this, 'pressed');
48
+ start(event) {
49
+ var btn = event.target;
50
+ var btn = getTargetIn(b => hasClass(b, 'button'), event.target);
51
+ if (btn.pressed) return;
52
+ btn.pressed = true;
53
+ var { oscillator, audioCtx, gainNode } = init(btn);
54
+ setBuffer(btn);
55
+ audioCtx.resume();
56
+ addClass(btn, 'pending');
57
+ if (!event.touches) mouse_target = btn;
31
58
  },
32
- end() {
33
- var { gainNode, oscillator, audioCtx } = this;
59
+ async end(event) {
60
+ if (!event.touches) var btn = mouse_target;
61
+ else var btn = getTargetIn(b => hasClass(b, 'button'), event.target);
62
+ if (!btn) return;
63
+ btn.pressed = false;
64
+ var { gainNode, oscillator, audioCtx } = btn;
34
65
  if (!gainNode || !oscillator) return;
35
- gainNode.gain.exponentialRampToValueAtTime(0.001, audioCtx.currentTime + 1);
36
- oscillator.stop(audioCtx.currentTime + 1);
37
- this.audioCtx = null;
38
- this.oscillator = null;
39
- this.gainNode = null;
40
- removeClass(this, 'pressed');
66
+ await audioCtx.suspend();
67
+ drop(btn);
68
+ removeClass(btn, 'pending');
41
69
  }
42
70
  }
71
+ on("touchstart")(page, click.start);
72
+ on("touchend")(page, click.end);
73
+ on('mousedown')(page, click.start);
74
+ bind('mouseup')(page, click.end);
43
75
  renderWithDefaults(page, {
44
76
  rates: piano(),
45
77
  audioCtx: null,
46
78
  gainNode: null,
47
79
  oscillator: null,
48
- button(a) {
49
- var b = button(a);
50
- moveupon(b, click);
51
- return b;
52
- },
53
80
 
54
81
  format(o) {
55
82
  var i = o.toFixed(1).indexOf('.');
@@ -48,7 +48,7 @@
48
48
  box-shadow: 0 0 12px -4px #0003;
49
49
  }
50
50
 
51
- &.active {
51
+ &.pending {
52
52
  z-index: 0;
53
53
 
54
54
  >.track {
@@ -108,7 +108,7 @@
108
108
 
109
109
  }
110
110
 
111
- button.pressed {
111
+ button.pending {
112
112
  color: red;
113
113
  }
114
114
 
@@ -59,7 +59,7 @@ function drag(target, initialEvent, preventOverflow, isMovingSource) {
59
59
  }
60
60
  var extraClones;
61
61
  var mousemove = function (event) {
62
- if (event.moveLocked) return;
62
+ if (+event.moveLocked === 1) return;
63
63
  if (/resize/i.test(getComputedStyle(document.body).cursor)) return;
64
64
  if (!saved_delta.ing) {
65
65
  var [target_left, target_top] = getOffset(target);