efront 3.9.9 → 3.9.15

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,4 +1,4 @@
1
- / authorization:
1
+ / authorization=:
2
2
  login: options ::login-:a
3
3
  run: options :::run
4
4
  share: options ::share-:opt?:path
@@ -4,17 +4,17 @@ var fields = refilm`
4
4
  服务器地址/host* select?a ${hosts}
5
5
  密码/password* password
6
6
  `;
7
- function main() {
7
+ function main(host) {
8
8
  var page = view();
9
9
  page.innerHTML = login;
10
10
  drag.on(page);
11
+ fields[0].readonly = !!host;
11
12
  on("append")(page, function () {
12
13
  move.bindPosition(page, [.5, .5]);
13
14
  });
14
15
  renderWithDefaults(page, {
15
16
  fields, data: {
16
- host: data.getInstance("base").host || location.host,
17
-
17
+ host: host ? parseURL(host).host : data.getInstance("base").host || location.host,
18
18
  }, pending: false
19
19
  });
20
20
  on("submit")(page, async function () {
@@ -23,16 +23,22 @@ function main() {
23
23
  this.$scope.pending = true;
24
24
  page.disabled = true;
25
25
  try {
26
- var login = await data.getApi("login");
27
- login.base = location.protocol + "//" + parseURL(this.$scope.data.host).host + "/";
28
- data.setInstance("base", { base: login.base, host: parseURL(login.base).host });
29
- var info = await data.from(login, {
26
+ var base = location.protocol + "//" + parseURL(this.$scope.data.host).host + "/";
27
+ if (!host) data.setInstance("base", { base, host: parseURL(base).host });
28
+ var api = Object.assign({}, await data.getApi("login"));
29
+ api.base = base;
30
+ var info = await data.from(api, {
30
31
  a: encode62.timeencode(encode62.geta(password))
31
32
  }).loading_promise;
32
33
  info = encode62.timeupdate(info);
33
- data.setSource({ authorization: info });
34
- user.login({})
35
- go('/main')
34
+ data.setSource(base, info);
35
+ if (host) {
36
+ cast(page, 'login', info);
37
+ remove(page);
38
+ } else {
39
+ user.login({});
40
+ go('/main');
41
+ }
36
42
  } catch (e) {
37
43
  console.log(e);
38
44
  }
@@ -4,6 +4,9 @@
4
4
 
5
5
  [foot],
6
6
  [head] {
7
+ &::before{
8
+ display: none;
9
+ }
7
10
  text-align: center;
8
11
  }
9
12
  .button{
@@ -15,7 +15,7 @@ function main() {
15
15
  target.removeAttribute('pending');
16
16
  },
17
17
  async logout() {
18
- data.setSource('authorization', null);
18
+ data.setSource({});
19
19
  await user.Logout();
20
20
  zimoli.switch();
21
21
  zimoli();
@@ -1,26 +1,54 @@
1
1
  data.loadConfig("api.yml");
2
2
  user.loginPath = '/auth/login';
3
- var token = data.getSource('authorization');
4
- if (token) {
5
- user.login({});
6
- }
3
+ cross.addReform(async function ({ status, url, headers }, reform, reject) {
4
+ if (status === 401) {
5
+ var base = data.getInstance("base").base;
6
+ var { protocol, host } = parseURL(url);
7
+ var base1 = protocol + "//" + host + "/";
8
+ if (base !== base1) {
9
+ data.setSource(base1, null);
10
+ var page = await popup("/auth/login", base1);
11
+ care(page, "login", function (info) {
12
+ data.setSource(base1, info);
13
+ headers.authorization = info;
14
+ reform();
15
+ });
16
+ on("remove")(page, reject);
17
+ return false;
18
+ }
19
+ location.reload();
20
+ }
21
+ })
22
+ data.setReporter(function (m, t) {
23
+ alert(m, t);
24
+ });
7
25
  data.bindInstance("base", async function (base) {
26
+ if (!base.base) return;
8
27
  cross.addDirect(base.base);
9
28
  var apimap = await data.getConfig();
10
29
  for (var k in apimap) {
11
30
  apimap[k].base = base.base;
12
31
  }
13
32
  });
33
+ var base = data.getInstance('base').base;
34
+ var token = base && data.getSource(base);
35
+ if (token) {
36
+ user.login({});
37
+ }
14
38
  setInterval(function () {
15
- var auth = data.getSource('authorization');
16
- if (!auth) return;
39
+ var base = data.getInstance("base");
40
+ if (!base.base) return user.token = null;
41
+ var auth = data.getSource(base.base);
42
+ if (!auth) return user.token = null;
17
43
  var auth1 = encode62.timeupdate(auth);
18
- if (auth1 !== auth) data.setSource("authorization", auth1);
44
+ if (auth1 !== auth) data.setSource(base.base, auth1);
19
45
  user.token = auth1;
20
46
  }, 2000);
21
47
  login();
22
48
  var layer = layer$glance({
23
- left: frame$left,
49
+ left: frame$left.bind({
50
+ head: await init("left-header")
51
+ }),
24
52
  top: frame$top
25
53
  });
26
54
  on("append")(layer, function () {
@@ -2,6 +2,7 @@ function main(a) {
2
2
  var page = view();
3
3
  page.innerHTML = template;
4
4
  drag.on(page.firstChild, page);
5
+ resize.on(page);
5
6
  var fields = data.from("params", { key: a.key }, function (a) {
6
7
  return a ? JSON.parse(encode62.timedecode(a)) : [];
7
8
  });
@@ -3,12 +3,21 @@ plist.bind(null, '任务管理', "task", refilm`
3
3
  *任务名/name 100
4
4
  *是否启用/status radio [不启用,启用]
5
5
  任务代码/code text
6
- 执行/ - ${[{
6
+ / - ${[
7
+ {
7
8
  when(o) {
8
9
  return o.status === 1;
9
10
  },
10
11
  name: "执行", do(o) {
11
12
  popup("/task/invoke", o);
12
13
  }
13
- }]}
14
- `, '/task/edit');
14
+ },
15
+ {
16
+ when(o) {
17
+ return o.status === 1;
18
+ },
19
+ name: "同步", do(o) {
20
+ popup("/task/rsync", o);
21
+ }
22
+ },
23
+ ]}`, '/task/edit');
@@ -0,0 +1,16 @@
1
+ <div head>
2
+ 同步任务&nbsp;-&nbsp; <span -text=task.name></span>(<span -text=task.key></span>)
3
+ <close @click="remove()"></close>
4
+ </div>
5
+ <div body>
6
+ <padding ng-repeat="h in hosts">
7
+ <a @click="checked[h.key]=!checked[h.key]" disabled:="h.key===base.host" :class="{finished:finished[h.key]}">
8
+ <checker -model="checked[h.key]"></checker>
9
+ <span -text="h.name"></span>
10
+ <span v-if="h.key===base.host">(当前)</span>
11
+ </a>
12
+ </padding>
13
+ </div>
14
+ <div foot>
15
+ <btn @click="flush()">同步</btn>
16
+ </div>
@@ -0,0 +1,39 @@
1
+ function main(task) {
2
+ var page = view();
3
+ page.innerHTML = template;
4
+ drag.on(page.firstChild, page);
5
+ resize.on(page);
6
+ renderWithDefaults(page, {
7
+ task,
8
+ checkbox(e) {
9
+ e = checkbox(e);
10
+ cast(e, { options: this.hosts })
11
+ },
12
+ base: data.getInstance("base"),
13
+ hosts: data.getInstance("hosts"),
14
+ finished: {},
15
+ checked: {},
16
+ async flush() {
17
+ var api = await data.getApi("edit");
18
+ api = Object.assign({}, api);
19
+ var finished = this.finished = {};
20
+ var checked = this.checked;
21
+ for (var h of this.hosts) {
22
+ if (!checked[h.key]) continue;
23
+ api.base = location.protocol + "//" + h.key + "/";
24
+ cross.addDirect(api.base);
25
+ await data.from(api, {
26
+ type: "task",
27
+ key: encode62.timeencode(task.key),
28
+ value: encode62.timeencode(JSON.stringify(task))
29
+ });
30
+ finished[h.key] = true;
31
+ }
32
+ alert('同步完成!');
33
+ },
34
+ remove() {
35
+ remove(page);
36
+ },
37
+ });
38
+ return page;
39
+ }
@@ -0,0 +1,10 @@
1
+ a{
2
+ cursor: pointer;
3
+ vertical-align: top;
4
+ >*{
5
+ vertical-align: middle;
6
+ }
7
+ &.finished{
8
+ color:#293;
9
+ }
10
+ }
@@ -10,7 +10,7 @@ function main() {
10
10
  if (!$scope.pathlist.length) {
11
11
  return;
12
12
  }
13
- $scope.pathlist.pop();
13
+ data.setInstance("pathlist", $scope.pathlist.slice(0, -1));
14
14
  $scope.open();
15
15
  return false;
16
16
  }
@@ -18,11 +18,11 @@ function main() {
18
18
 
19
19
  renderWithDefaults(page, {
20
20
  lattice,
21
- pathlist: [],
21
+ pathlist: data.getInstance("pathlist"),
22
22
  active: null,
23
23
  open(p) {
24
24
  if (p) p = String(p.name || '').replace(/\/$/, '');
25
- if (p) this.pathlist.push(p);
25
+ if (p) data.setInstance("pathlist", this.pathlist.concat(p));
26
26
  this.data = data.from("folder", { opt: 'list', path: "/" + this.pathlist.join('/') }, files => {
27
27
  if (files) return sortname(files).map(f => {
28
28
  return {
@@ -503,11 +503,19 @@ var createModule = function (exec, originNames, compiledNames, prebuilds = {}) {
503
503
  var promise = new Promise(function (ok) {
504
504
  _ok = ok;
505
505
  });
506
+ if (prebuilds.init) {
507
+ var prebuilds2 = Object.create(null);
508
+ for (var k in prebuilds) prebuilds2[k] = prebuilds[k];
509
+ prebuilds = prebuilds2;
510
+ delete prebuilds.popup;
511
+ delete prebuilds.action;
512
+ delete prebuilds.init;
513
+ }
506
514
  init(argName, function (res) {
507
515
  result = res;
508
516
  created = true;
509
517
  _ok(res);
510
- });
518
+ }, prebuilds);
511
519
  if (created) return result;
512
520
  return promise;
513
521
  });
@@ -1,5 +1,5 @@
1
- // -------/// ---------------1-------------//////////////2---3--------//////// ----4----2/////5-----------------------6-----------------------//////////////-7--5///8----9----//10--11---10///--12-----8//
2
- var reg = /^([^\:\/\?#\[]+\:(?![^\:\/\?\#]*@))?(?:\/\/)?(?:(([^\:\/\?#]+)?(?:\:([^\/\?#]+))?)@)?(([^\/@\:\?\#]*(?:[^\d\@\:\/\?#]|\.)[^\/@\?\#]*?)?(?:(?:\:|^)(\d+))?)((\/[^\?#]*)?(\?([^#]*))?(#[\s\S]*)?)$/;
1
+ // -------/// ---------------1---------------------------------///////////////////2-----3--------//////// ------4----2/////5---------------------------------------------------6-----------------------------------------------------------------------------//////////////-7--5///8-------9----------//10--11---10///--12-----8//
2
+ var reg = /^([^\:\/\\\?#\[]+\:(?![^\:\/\\\?\#]*@|[\/\\][^\/\\]))?(?:\/\/|\\\\)?(?:(([^\:\/\\\?#]+)?(?:\:([^\/\\\?#]+))?)@)?(([^\/\\@\?\#\.]*?[^\/\\@\:\?\#\.\d][^\/\\@\:\?\#\.]*?|[^\/\\@\:\?\#\.]+(?:\:[\@\/\\\?#\.]*[^\d\@\:\/\\\?#\.]+|\.[^\/\\@\:\?\#]+?))?(?:(?:\:|^)(\d+))?)(((?:\/|\\|^)[^\?#]*)?(\?([^#]*))?(#[\s\S]*)?)$/;
3
3
  function parseURL(url) {
4
4
  if (url === undefined || url === null) url = '';
5
5
  var [__, protocol, auth, username, password, host, hostname, port, path, pathname, search, query, hash] = reg.exec(url);
@@ -36,4 +36,10 @@ test("http://[::]/", "host", "[::]")
36
36
  test("http://[::%12]/", "host", "[::%12]")
37
37
  test("http://[::]:80/", "hostname", "[::]")
38
38
  test("[::]:80/", "hostname", "[::]")
39
- test("[fd64:f52:f52:f52:f52:f52:f52:97]", "hostname", "[fd64:f52:f52:f52:f52:f52:f52:97]")
39
+ test("[fd64:f52:f52:f52:f52:f52:f52:97]", "hostname", "[fd64:f52:f52:f52:f52:f52:f52:97]")
40
+ test("./cluster-opt.html", "pathname", "./cluster-opt.html")
41
+ test(":cluster-opt.html", "pathname", ":cluster-opt.html")
42
+ test("d:/cluster-opt.html", "pathname", "d:/cluster-opt.html")
43
+ test("d:\\cluster-opt.html", "pathname", "d:\\cluster-opt.html")
44
+ test("ftp:\\\\cluster-opt.html", "host", "cluster-opt.html")
45
+ test("\\\\cluster-opt.html", "host", "cluster-opt.html")
@@ -1,10 +1,11 @@
1
1
  var seek = function (object, seeker) {
2
- if (seeker === null || seeker === undefined || !object) return;
2
+ if (seeker === null || seeker === undefined || isEmpty(object)) return;
3
3
  if (seeker instanceof Function) {
4
4
  return seeker(object);
5
5
  }
6
6
  if (typeof seeker === "string") {
7
7
  if (/^(['"`])[\s\S]*$/i.test(seeker)) return seeker.replace(/^(['"`])([\s\S*])\1?$/, "$2");
8
+ if (seeker === '' || seeker === ".") return object;
8
9
  seeker = seeker.split(".");
9
10
  }
10
11
  if (seeker instanceof Array) {
@@ -82,17 +82,17 @@ var parse干支 = function (a) {
82
82
  return (12 + g - z) % 12 / 2 * 10 + g + 1;
83
83
  };
84
84
  var compare = function (a, b) {
85
- for (var cx1 = a.length - 1, cx2 = a.length - 1; cx1 >= 0 && cx2 >= 0; cx1--, cx2--) {
85
+ for (var cx1 = a.length - 1, cx2 = b.length - 1; cx1 >= 0 && cx2 >= 0; cx1--, cx2--) {
86
86
  while (/\s\u00a0/.test(a[cx1])) cx1--;
87
87
  while (/\s\u00a0/.test(b[cx2])) cx2--;
88
- if (a[cx1] !== b[cx2] || a[cx1] in map子丑寅 || a[cx1] in map一二三 || a in power) break;
88
+ if (a[cx1] !== b[cx2] || a[cx1] in map子丑寅 || a[cx1] in map一二三 || a in power || /^\d$/.test(a[cx1])) break;
89
89
  }
90
90
  a = a.slice(0, cx1 + 1);
91
91
  b = b.slice(0, cx2 + 1);
92
- for (var cx1 = 0, cx2 = 0, dx1 = a.length, dx2 = b.length; cx1 < dx1 && cx2 < dx2; cx1++, cx2++) {
92
+ for (var cx1 = 0, cx2 = 0, dx1 = b.length, dx2 = b.length; cx1 < dx1 && cx2 < dx2; cx1++, cx2++) {
93
93
  while (/[\s\u00a0]/.test(a[cx1])) cx1++;
94
94
  while (/[\s\u00a0]/.test(b[cx2])) cx2++;
95
- if (a[cx1] !== b[cx2] || a[cx1] in map甲乙丙 || a[cx1] in map一二三 || a in power) break;
95
+ if (a[cx1] !== b[cx2] || a[cx1] in map甲乙丙 || a[cx1] in map一二三 || a in power || /^\d/.test(a[cx1])) break;
96
96
  }
97
97
  if (cx1) a = a.slice(cx1);
98
98
  if (cx2) b = b.slice(cx2);
@@ -22,6 +22,11 @@ function main(title, { submit }, { data: origin, fields, }) {
22
22
  dispatch(this, 'submited');
23
23
  remove(this);
24
24
  });
25
+ bind('keydown.ctrl.s')(page, async function (e) {
26
+ e.preventDefault();
27
+ await submit(item, fields);
28
+ dispatch(this, 'submited');
29
+ });
25
30
  on("append")(page, lazy(function () {
26
31
  page.querySelector("input").focus();
27
32
  }));
@@ -1,13 +1,13 @@
1
- <div ng-if="!user.isLogin" class="navbar-header">
1
+ <header ng-if="!user.isLogin" class="navbar-header">
2
2
  <!-- <avatar></avatar> -->
3
3
  <a @click="popup('#/user/login')" class="dashboard_text">请登录</a>
4
- </div>
5
- <div -else class="navbar-header">
4
+ </header>
5
+ <header -else class="navbar-header">
6
6
  <span class="dashboard_text" @click="go('/user/profile')">
7
7
  <avatar ng-src="user.avatar" size=30></avatar>
8
8
  <span ng-bind="user.name"></span>
9
9
  <span ng-bind="user.roles"></span>
10
10
  </span>
11
- </div>
11
+ </header>
12
12
  <ylist mode=inline ng-src="menu in menus" class="sidebar-menu" ng-active="menus.open(event.value)">
13
13
  </ylist>
@@ -1,18 +1,21 @@
1
- var page = document.createElement("都说我负天下人_可你们天下人_又何曾善待过我");
2
- page.innerHTML = left;
3
1
  if (!user.avatar) user.avatar = "user/avatar.png";
4
- render(page, {
5
- ylist: menu,
6
- btn: button,
7
- go,
8
- user,
9
- avatar,
10
- popup,
11
- menus: frame$route,
12
- });
13
- on('append')(page, function () {
14
- frame$route.open();
15
- });
16
2
  function main() {
3
+ var page = document.createElement("都说我负天下人_可你们天下人_又何曾善待过我");
4
+ page.innerHTML = template;
5
+ var { head, foot, header = head, footer = foot } = this;
6
+ render(page, extend({
7
+ ylist: menu,
8
+ btn: button,
9
+ go,
10
+ user,
11
+ avatar,
12
+ header,
13
+ footer,
14
+ popup,
15
+ menus: frame$route,
16
+ }, this));
17
+ on('append')(page, function () {
18
+ frame$route.open();
19
+ });
17
20
  return page;
18
21
  }
@@ -4,13 +4,14 @@
4
4
  }
5
5
 
6
6
  .navbar-header {
7
- height: 50px;
7
+ min-height: 50px;
8
8
  padding: 10px 15px 10px 25px;
9
9
  font-size: 25px;
10
10
  line-height: 25px;
11
11
  text-transform: uppercase;
12
12
  color: #b8c7ce;
13
13
  margin-top: -50px;
14
+ display: block;
14
15
  }
15
16
 
16
17
  .dashboard_text {
@@ -5,7 +5,6 @@ function main(title, { fields, options: options0, load, remove }, edit_ref) {
5
5
  zimoli.prepare(edit_ref, function () {
6
6
  var p = popup(edit_ref, { fields, data: o })
7
7
  on("submited")(p, function () {
8
- console.log("submited")
9
8
  page.$scope.load();
10
9
  })
11
10
  })
@@ -0,0 +1 @@
1
+ <select -model="host" @change="setHost(this.value)" direction=y addable><option -repeat="h in hosts" :value=h.key -text="h.name"></option></select>
@@ -0,0 +1,15 @@
1
+ function main() {
2
+ var a = document.createElement("菜单之上");
3
+ a.innerHTML = template;
4
+ render(a, {
5
+ setHost(a) {
6
+ data.setInstance("base", { base: location.protocol + "//" + a + "/", host: a });
7
+ data.abortAll();
8
+ zimoli();
9
+ },
10
+ host: data.getInstance("base").host,
11
+ select,
12
+ hosts: data.getInstance("hosts")
13
+ });
14
+ return a;
15
+ }
@@ -0,0 +1,11 @@
1
+ &.navbar-header {
2
+ padding: 0;
3
+ }
4
+
5
+ select {
6
+ background: transparent;
7
+ color: inherit;
8
+ height: 50px;
9
+ margin: 0;
10
+ width: 100%;
11
+ }
@@ -35,6 +35,8 @@ function alert() {
35
35
  [].map.call(arguments, function (arg) {
36
36
  switch (typeof arg) {
37
37
  case "string":
38
+ case "object":
39
+ arg = String(arg);
38
40
  if (!text) {
39
41
  text = arg;
40
42
  } else if (color_reg.test(text)) {
@@ -0,0 +1,14 @@
1
+ function bind(eventName, bindTo = window) {
2
+ return function (target, eventListener) {
3
+ var off;
4
+ var off1 = on("append")(target, function () {
5
+ if (off) off();
6
+ off = on(eventName).call(bindTo, target, eventListener);
7
+ });
8
+ var off2 = on("remove")(target, function () {
9
+ if (off) off();
10
+ off = null;
11
+ });
12
+ return function () { off1(); off2(); };
13
+ }
14
+ }
@@ -183,6 +183,7 @@ a&,
183
183
  color: @default-color;
184
184
  cursor: pointer;
185
185
  outline: none;
186
+ .clear();
186
187
 
187
188
  .clear() {
188
189
  text-shadow: none;
@@ -8,7 +8,7 @@ function create(commFactory, className) {
8
8
  }
9
9
  if (isFunction(commFactory)) {
10
10
  var result = function () {
11
- var commRelease = commFactory.apply(result, arguments);
11
+ var commRelease = commFactory.apply(this || result, arguments);
12
12
  if (commRelease) {
13
13
  commRelease = create(commRelease, className);
14
14
  }
@@ -154,13 +154,19 @@ function cross(method, url, headers) {
154
154
  xhr.onerror = function (e) {
155
155
  onerror(e);
156
156
  };
157
+ xhr.abort = function () {
158
+ removeFromList(requests, this);
159
+ remove(this);
160
+ };
157
161
  } else {
158
162
  var nocross = notCross(url);
159
163
  var xhr = new XMLHttpRequest;
160
164
  var abort = xhr.abort;
161
165
  xhr.abort = function () {
162
166
  xhr.onreadystatechange = null;
167
+ removeFromList(requests, this);
163
168
  abort.call(this);
169
+ clearTimeout(sendtimer);
164
170
  };
165
171
 
166
172
  xhr.onreadystatechange = function () {
@@ -217,8 +223,7 @@ function cross(method, url, headers) {
217
223
  onerrors.push(oh);
218
224
  flush();
219
225
  };
220
- setTimeout(function () {
221
- digest();
226
+ var fire = function () {
222
227
  var isform = /^f/i.test(method);
223
228
  if (isform) {
224
229
  if (method === 'form') method = 'post';
@@ -248,10 +253,13 @@ function cross(method, url, headers) {
248
253
  }
249
254
  Object.keys(realHeaders).forEach(key => setRequestHeader.call(xhr, key, realHeaders[key]));
250
255
  send.call(xhr, datas);
251
- }, 0);
256
+ digest();
257
+ };
258
+ var sendtimer = setTimeout(fire, 0);
252
259
  }
253
260
  var loaded, errored;
254
261
  var onload = function (xhr) {
262
+ removeFromList(requests, xhr);
255
263
  if (xhr.decoder) {
256
264
  xhr = xhr.decoder(xhr);
257
265
  }
@@ -259,11 +267,19 @@ function cross(method, url, headers) {
259
267
  flush();
260
268
  digest();
261
269
  };
262
- var onerror = function (xhr) {
263
- errored = xhr;
270
+ var onerror1 = function (e) {
271
+ removeFromList(requests, e);
272
+ errored = e || "未知错误!";
264
273
  flush();
265
274
  digest();
266
275
  };
276
+ var onerror = async function (e) {
277
+ for (var r of reforms) {
278
+ var r = await reform(r, { method, url, status: xhr.status, headers: _headers }, fire, onerror1, e);
279
+ if (r === false) return;
280
+ }
281
+ onerror1(e);
282
+ };
267
283
  var flush = function () {
268
284
  var then = xhr.then;
269
285
  delete xhr.then;
@@ -317,9 +333,11 @@ function cross(method, url, headers) {
317
333
  flush();
318
334
  return xhr;
319
335
  };
336
+ requests.push(xhr);
320
337
  return xhr;
321
338
  }
322
339
  function addDirect(a) {
340
+ if (cors_hosts.indexOf(a) >= 0) return;
323
341
  if (typeof a === 'string' || a instanceof RegExp) cors_hosts.push(a);
324
342
  }
325
343
  function notCross(domain) {
@@ -335,8 +353,32 @@ function notCross(domain) {
335
353
  }
336
354
  return false;
337
355
  }
356
+
357
+ var requests = [];
358
+ var reforms = [];
359
+ function reform(r, info, fire, cancel, e) {
360
+ var fired = false;
361
+ return r(info, function () {
362
+ if (fired) return;
363
+ fired = true;
364
+ fire();
365
+ }, function () {
366
+ if (fired) return;
367
+ fired = true;
368
+ cancel(e);
369
+ })
370
+ }
371
+ function addReform(r) {
372
+ if (isFunction(r)) reforms.push(r);
373
+ }
338
374
  extend(cross, {
375
+ requests,
376
+ abortAll() {
377
+ var rs = requests.splice(0, requests.length);
378
+ for (var r of rs) r.abort();
379
+ },
339
380
  setHost,
381
+ addReform,
340
382
  getCookies,
341
383
  addCookie,
342
384
  addDirect,